Clever way to manage browser history - javascript

I'm trying to implement a decent navigation in a AJAX application. What I am doing right now is the following:
Every time a user clicks an AJAX link, the corresponding call is performed and the hash is changed.
Whenever a new page is loaded, I check whether the hash is present and make the corresponding AJAX call to update the page. This ensures that bookmarks will work as expected.
Every 500ms I check if the hash is changed and perform the corresponding AJAX call. This takes care of users pressing the back/forward buttons, albeit with a sligth delay.
The third point is a bit annoying: I'd rather not have a timeout every 500ms just to check the hash, as most of the time it will stay the same.
Is there a better way to manage this? I cannot think of any alternatives, but maybe I am missing something.
Please, do not point me towards ready-made solutions, unless you know they are based on a different mechanism.

There is the "hashchange" event, which is to be implemented in HTML5. I'm not sure how good support is now... IE8 supports it, and I think Mozilla have their own implementation in a recent release. Other than that, there is nothing I'm afraid. Checking exery x ms is the way everyone does it.

maybe this is an interesting read, it is a ready made solution for the exact thing you are doing.
and no, until the hashchange is properly supported in every browser (read: ie), you will have to check manually

Use this plugin: http://www.asual.com/jquery/address/
The jQuery Address plugin provides powerful deep linking capabilities and allows the creation of unique virtual addresses that can point to a website section or an application state. It enables a number of important capabilities including:
Bookmarking in a browser or social website
Sending links via email or instant messenger
Finding specific content using the major search engines
Utilizing browser history and reload buttons

Related

How to detect whether a HTML file is opened in browser or some Application Software?

I need to do some changes in my HTML file based on whether it is opened in browser or Some Desktop Application.
Till now I've tried this in my script:
alert(navigator.appName);
alert(navigator.appCodeName);
alert(navigator.platform);
But the values are coming same whether the HTML file is opened in browser or some application Software.
How can i set a variable which toggle its value from 0 to 1 when opened in application Software and vice versa.
PS: Application Software like Matlab, MS Office , Britanica Encyclopedia etc.
Short answer, you can't.
Longer answer, to some extent. What you need to do is make a list of differences in each desktop apps implementation, based on known flaws, missing/existing properties, user agent flavours and so on (some of this called "browser spoofing"), to be able to sort them out. It will still be possible to trick this if one want to though.
Normally there is another way of dealing with the differences, the question is what is the different behaviour you want between the 2?
As a sample, and if you still need/insists to detect this, there is device detection libraries which can help as a start, like https://51degrees.com/device-detection
I still recommend to find another way to solve it.
UPDATE
As it is easy to create a desktop app and return the values needed for your page to believe it is a normal browser, I think the best solution is to ask the user on first page hit if they are on a normal browser or not (the one who is not will normally know) and then store in a cookie/set a flag and act upon what the user selected.
I mean it is easy to cheat your page either way so better trust on user selection.
You can use 2 step verification for such cases as devices are getting quite varied. First you can detect devices by media queries strings using innerWidth property. And then you can apply second filter matched by protocol it supports.
Secondly, this SO question might help Frame Buster Buster ... buster code needed

Refreshing webpage after browser back button?

Let me begin by saying I do not want to "disable" or otherwise prevent the proper usage of the browser history buttons.
What I need is a javascript-based procedure (cross-browser compatible, hopefully) to refresh a webpage (staying on the same URL) after navigating to it using the back/forward buttons. This is necessary because during this process the server keeps track of the user's position/page, and if the user wants to jump back 3 pages I need to "inform" the server of the new location by reloading the page (or is there a better way to do it?) I already disabled caching through HTTP headers but this doesn't work for back/forward history, at least in Firefox 7.
Using jQuery is of course acceptable and desirable. I looked around a bit and found out about $(document).ready(). Now, please keep in mind I'm a complete javascript noob. I have zero experience, and the same goes for jQuery (I know what it does, I've looked at the docs, but that's about it). So I'm trying to understand how this works, but pages that mention this method seem to assume that the webdeveloper wants to modify the DOM from it, and there are a few quirks when you want to do that (load order and stuff). Since in my case I only need to refresh, it should hopefully be easier. So:
I understand this doesn't only run when you browse back, it also runs every time you load the page. How can I make sure I don't end up with an infinite loop? I want it to run once when I browse back, but not on load, after the automated refresh or otherwise. On a normal load I'd rather not have it running because the user would have to download each page twice, which is stupid!
Or is there a better way to do this? Any other ideas? Care to explain or point me in the right direction?
EDIT: I only need compatibility with:
Internet Explorer 8 or higher
Firefox 4 or higher
Recent-ish Chrome/Safari (I don't keep track of version numbers but why would someone not use up to date Chrome anyway?)
The best workaround I ever found for this problem is to use location.replace(), like so.
It does not directly address the problem from my original question; however, since that seems not to have a solution (for now), I recommend that everyone uses this client side function to protect the server side pages they do not wish to have executed again by a client using the back button. I'm sure this is better explained elsewhere on stackoverflow, but for the few people using my convoluted way of thinking to look the problem up, there you have it.
Its a bit of an abuse, but one of the ways of doing this would be to have your "proceed to next step" button as a form which POSTs. For example;
instead of
Proceed to next Page
you have
<form action = "foo" method = "POST"><input type = "submit" value = "Proceed to next page" /></form>
If the user hits back, they'll be forced to re-send their data to the server and your page would be refreshed. This would probably be really annoying to the user though!
But as i mentioned, major abuse of forms!
EDIT: This abuse will only work for certain scenarios though, you'll be the best judge of whether it's appropriate.

How facebook overwrite link? [duplicate]

Go to http://www.facebook.com/facebook?v=wall, then click on the info tab. The content will be loaded, and the address bar now becomes http://www.facebook.com/facebook?v=info but the webpage didn't reload.
At first I think it is Ajax, but my question is, how do you change the address bar without reloading? I know I can change anchor (#wall) using JS but querystring (?v=wall), how?
It's using HTML5's new history.pushState() feature to allow the page to masquerade as being at a different URL to that from which it was originally fetched.
This seems only to be supported by WebKit at the moment, which is why the rest of us are seeing ?v=wall#!/facebook?v=info instead of ?v=info.
The feature allows dynamically-loaded pages to be properly bookmarked, exchanged etc between JS-supporting and non-JS-supporting user agents. Because if you as a JS user linked someone to ?v=wall#!/facebook?v=info and their browser didn't support JS and XMLHttpRequest, the page wouldn't work for them. The #! is also used as a tip to search engines to download the non-AJAX version.
#Snoob - I'd appreciate it if you accepted #bobince's answer instead, he's was on the right track about the specifics first here. Since I can't delete/remove this until it's unaccepted I'll update it to be as correct as possible.
At the moment it's a WebKit (Chrome, Safari, etc.) specific thing you're seeing (or rather, not seeing), as #bobince points out in other browsers you can see the real URL in the bar:
http://www.facebook.com/facebook?v=wall#!/facebook?v=info\
Where Chrome just shows:
http://www.facebook.com/facebook?v=info
It makes a bit of sense, given this is how you make AJAX Content crawlable with the Google search engine, so their browser recognizes where the content comes from as well.
Correction on the specifics: Webkit browsers are showing the shortened URL facebook wants using the HTML 5 history features you can see the code here (take a look at the HistoryManager) in this case specifically they're using .replaceState() to replace the URL you went to with the direct one available.
Note: This answer may not be valid later (the WebKit specific bit), as other browsers support HTML5 features more and more this may become outdated quickly.
For MooTools developers I recommend checking out cpojer's mootools-history plugin which provides support for the native history API when available, with a fallback to hashes.
I don't have Facebook so I can't check. But I'm 95% sure that it has to be a full page request, the location bar is unwritable because this would be a very useful feature to absure for phishing websites (instead of http://fakeonlinebank.com it rewrite to http://yourtrustybank). It's probably just so fast that your browser appears to only load that part?
But I'm curious to see if someone will correct me on this, because that would mean they have the answer you do want to hear ;)

How to externally influence JavaScript running in a page

I'd like to be able to make the JavaScript I've got in a web page behave differently by doing something or setting something externally. So there'll be logic checking if(something) execute functionality one, else execute functionality two. I can think of three ways of doing this, but I don't like any of them enough to choose it. At least not unless I can see if there's another blindingly obvious way of doing it that's somehow escaping me at the moment.
Add a harmless query string to the URL (e.g. ?choose_functionality_one=true) and my logic can simply look in the page URL. The reason I don't like this is the case where my code is running inside a cross-domain iframe and I can't even access the page's URL (only the iframe's URL). Yes I could pass the query string to the iframe, but only if I have control over the parent page, and I don't.
Create a cookie in the domain of the page, and my logic can simply look for it in document.cookie. This could be done with a bookmarklet easily enough, and wouldn't suffer from the cross-domain problem, because I simply open a window/tab to the domain where my code is running and run the bookmarklet in that context. This is my front-runner choice at the moment.
Add something to the browser's useragent string and look for that in my logic. Pretty easy on Firefox via about:config, but is less easy with the other browsers, and downright difficult on the Mac. Also, on some browsers, once you've set a custom value, you lose the ability to have the UA get auto-updated when you get a browser update. Your UA's version info is stuck in time to where it was when you first custom'ed it.
Can anyone think of another way that via email/IM/phone I can say to someone "do this" and they'll see the page behave differently for troubleshooting purposes. For the general population who haven't done that though, it's running completely normally.
The simplest option seems to be to make a debug page on your site that will let the user turn the "debug" cookie on/off and then queue your regular site code off the existence of the cookie. I'd suggest making the debug cookie expire in a fairly short amount of time so people don't inadvertently leave it on.
This option has the advantages you are interested in (no user agent modification, works on all platforms, works with iframes) and I can see no disadvantages except that it wouldn't work if someone had cookies off, though a lot of the web won't work without cookies these days so that seems like something you could live with.
In addition, it's also the simplest for your users to use. You can just direct them to the right page on your site and all they have to do is click the desired button to turn it on or off. You can make the page very self explanatory which is certainly much easier than any of the other options.
OK, if you only control code and no HTML, then you could do either implement a keyboard shortcut key that would enable the debug mode by setting the cookie. The instructions could be something like this: put the keyboard focus in X and then press Ctrl-D.
Or, you could implement some special type of click (like a Ctrl-click on some object or in some page corner). In this case the instructions could be something like: Hold down the Ctrl-key and click on object X on the page.
Your JS code could implement either of those shortcuts. You could even put up a prompt (all with dynamically created HTML objects) when the special key/click was engaged to confirm turning the debug mode on or off.

How does facebook rewrite the source URL of a page in the browser address bar?

Go to http://www.facebook.com/facebook?v=wall, then click on the info tab. The content will be loaded, and the address bar now becomes http://www.facebook.com/facebook?v=info but the webpage didn't reload.
At first I think it is Ajax, but my question is, how do you change the address bar without reloading? I know I can change anchor (#wall) using JS but querystring (?v=wall), how?
It's using HTML5's new history.pushState() feature to allow the page to masquerade as being at a different URL to that from which it was originally fetched.
This seems only to be supported by WebKit at the moment, which is why the rest of us are seeing ?v=wall#!/facebook?v=info instead of ?v=info.
The feature allows dynamically-loaded pages to be properly bookmarked, exchanged etc between JS-supporting and non-JS-supporting user agents. Because if you as a JS user linked someone to ?v=wall#!/facebook?v=info and their browser didn't support JS and XMLHttpRequest, the page wouldn't work for them. The #! is also used as a tip to search engines to download the non-AJAX version.
#Snoob - I'd appreciate it if you accepted #bobince's answer instead, he's was on the right track about the specifics first here. Since I can't delete/remove this until it's unaccepted I'll update it to be as correct as possible.
At the moment it's a WebKit (Chrome, Safari, etc.) specific thing you're seeing (or rather, not seeing), as #bobince points out in other browsers you can see the real URL in the bar:
http://www.facebook.com/facebook?v=wall#!/facebook?v=info\
Where Chrome just shows:
http://www.facebook.com/facebook?v=info
It makes a bit of sense, given this is how you make AJAX Content crawlable with the Google search engine, so their browser recognizes where the content comes from as well.
Correction on the specifics: Webkit browsers are showing the shortened URL facebook wants using the HTML 5 history features you can see the code here (take a look at the HistoryManager) in this case specifically they're using .replaceState() to replace the URL you went to with the direct one available.
Note: This answer may not be valid later (the WebKit specific bit), as other browsers support HTML5 features more and more this may become outdated quickly.
For MooTools developers I recommend checking out cpojer's mootools-history plugin which provides support for the native history API when available, with a fallback to hashes.
I don't have Facebook so I can't check. But I'm 95% sure that it has to be a full page request, the location bar is unwritable because this would be a very useful feature to absure for phishing websites (instead of http://fakeonlinebank.com it rewrite to http://yourtrustybank). It's probably just so fast that your browser appears to only load that part?
But I'm curious to see if someone will correct me on this, because that would mean they have the answer you do want to hear ;)

Categories

Resources