I have a JS single-page app that uses the history API. A user lands on my page and navigates around, and a bunch of pushStates and replaceStates happen under the hood. All of the transitions happen in JS, no page reload happens. My question is that how can I detect if the user is back on the first location within my own app, that is, one more back button press will cause the browser to reload the previous page the user was on?
Thanks in advance!
You can detect the transition with hooking on onpopstate event and checking, where the user actually navigates:
https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onpopstate
Note however that if you'll try to stop such transition, this may be hard to do:
how to stop browser back button using javascript
You could use something like:
if(window.location == <the url of the root) {
//Do stuff here
}
Related
I am creating a web app using web socket, which on user closes the tab I will make an API call to the server to clean the user related info in the server, I used onBeforeUnload listener in javascript, but this method also gets triggered during the page refresh.
I need to trigger a method only during the tab or browser close, but not during the page refresh.
I know this question has been asked several times, some solution suggested using cookies will not be helpful in my case
navigator.sendBeacon() method can be used for sending data from browser to server when a tab is closed.
Here is an example:
window.addEventListener("unload", function informServer() {
navigator.sendBeacon("/server-api-to-collect-data", my-data)
})
More information:
https://developer.mozilla.org/en-US/docs/Web/API/Navigator/sendBeacon
As far as I know, you can not listen to actions of browser's tab close or exits. For your application it is an "unload", whatever caused it...
The only thing I could think about is maybe add a listener for keyboard key press (F5), however it doesn't help in case someone refreshed by clicking on the browser's refresh button.
I don't know what is the use case, but most of the things should be done when a page unloads (no matter why) and/or when the page is back up again. So most of the solutions are for situations where your page is loaded again - and then you can determine what was the source of the load and make farther actions, but since you have an option were someone can close and never come back, that might not be the case.
Some solutions for page load up:
You can use Navigation type.
You can check referer.
You can use cookies or other types of browser storage.
I would recommend to rethink about your use case. Maybe you can do whatever you want on load up or leave it on onBeforeUnLoad without knowing the future :)
I work in Ext JS. in Ext JS webdesktop application , when i click browser refresh button it reload and goes to login window. Because my first page is login. For this reason i need to stop this event or disable browser refresh button when this application launch. i can stop F5 but can't browser refresh button. So please some one help me for this issue.
Thanks...
No, wrong issue
You have to memorize the current View he is in. As far as i remember, Ext has mechanisms for that, otherwise you can still use a (session-)cooke.
and you don't have to start you application with the login-screen. It is just one view, and imo. the one you would want to use as few as possible.
So. on page load, check wether he is logged in, if no, show him the login-view, if yes check which view he was in and render it, otherwise send him to the start point.
this is basically the loop you have to send him through, on pageload, on refresh, onlogin, ...
I am trying a new functionality for my web site. I want to do simple navigation by hiding/showing <div> elements.
For example, when a user clicks a "details" button on some product, I want to hide the main <div> and show the <div> containing the details for the product.
The problem is that to go back to the previous "page", I have to undo all the display/visibility style changes, which is ok if the user clicks the "close" button in the newly opened <div>. But most users will hit the BACK button.
Is there a way to make the BACK button go back to the previous "state" of the page i.e., undo the visibility/display changes?
Thanks.
Yes. What you're looking for is called AJAX browser history.
There are a few open implementations out there, like RSH as well as plugins/modules for frameworks like jQuery and YUI.
to answer the question of your title (that's what I was looking for)
Using the BACK button to revert to the previous state of the page
and from the link from #reach4thelasers's answer, you have to set up a timer and check again and again the current anchor:
//On load page, init the timer which check if the there are anchor changes each 300 ms
$().ready(function(){
setInterval("checkAnchor()", 300);
});
because there's no Javascript callback triggered when the BACK button is pressed and only the anchor is changed ...
--
by the way, the pattern you're talking about is now known as Single Page Interface !
You need to add an anchor to the URL whenever a change is made
www.site.com/page.html#anchor1
This will allow the browser to maintain the pages in its history. I implemented it in my current site after following this tutorial, which works great and gives you a good understanding of what you need to do:
http://yensdesign.com/2008/11/creating-ajax-websites-based-on-anchor-navigation/
Your example in the comments won't work, because it works like this:
Page Loaded
Page Changed, Add Anchor to URL (back button takes you back to back to 1)
Page Changed, Anchor Changed (back button button takes you back to 2)
Page Changed, Anchor Changed (back button button takes you back to 3)
.... and so on and so on..
If there is, it sounds like a pretty evil thing to do from a UX perspective. Why don't you design a "back" button into your application, and use design to make it obvious to the user that they should use your application's back button instead of the browser.
By "use design," I mean make your application look like a self-sufficient user interface inside of the browser, so the user's eye stays within your page, and not up on the browser chrome, when they are looking for controls to interact with your app.
You can do this with anchors, which is how it's done in a lot of flash applications, or other apps that don't go from page to page. Facebook uses this technique pretty liberally. Each time the user clicks on a link that should go in their history, change the anchor on the page.
So say my home page link is:
http://www.mysite.com/#homepage
For the link that works your javascript magic, do this:
My Other Page
This will send the user to http://www.mysite.com/#otherpage where clicking the back button will go back to http://www.mysite.com/#homepage. Then you just have to read the anchors with
window.location.hash
to figure out which page you're supposed to be on.
Take a look to this tutorial based on ItsNat a Java web framework focused on Single Page Interface web sites
I am using History.js and Jquery (and a little GWT), I use the History.pushState() method to store the Ajax payload, then in the statechanged event I paint the screen according to the payload. Now inside my app the browswer back and forward buttons work correctly.
The strange thing is when users click a link in my app that takes them to a page that is outside of my app (same domain but another application), they go out, view the page, then hit the back button to re-enter my app.
My app loads, it does not receive a popstate or a statechange event, but somehow the browser is actually painting the screen to resemble exactly what it looked like before they left my app.
I'd like to understand what is happening here.
[EDIT: I was wrong. My code was executing and I did receive the statechange. I had some assumptions about History.js, and now I realize to code correctly, you should receive your AJAX payload, then call pushstate to put it on the stack. Then your statechange event will fire, and you should, in the statechange function, read the state off the stack and paint the screen accordingly. The same code will execute when you run your app normally, and the same code will execute when the user hits the back button. ]
You have to read the URL and then handle accordingly. It's the same as if you were deep linking into your application directly from the address bar.
It sounds like the browser is showing a cached state of the app instead of completely reloading it when the user uses the back button to return to the app.
You can test this by going into the app, clicking the outside app link, hitting the browser back button to go back, and then hitting refresh. If it changes the app state upon reload, it tells you that the browser was caching the app state instead of reloading.
Once the user is on my page, I do not want him to refresh the page.
Anytime, the user hits F5 or refresh button on top. He should get an alert saying
You cannot refresh the page.
Also if the user opens a new tab and tries to access the same url in prev tab he should get an alert
You cannot open same page in 2 tabs
Anyway I can do this using JavaScript or jQuery? Point one is really important.
#1 can be implemented via window.onbeforeunload.
For example:
<script type="text/javascript">
window.onbeforeunload = function() {
return "Dude, are you sure you want to leave? Think of the kittens!";
}
</script>
The user will be prompted with the message, and given an option to stay on the page or continue on their way. This is becoming more common. Stack Overflow does this if you try to navigate away from a page while you are typing a post. You can't completely stop the user from reloading, but you can make it sound real scary if they do.
#2 is more or less impossible. Even if you tracked sessions and user logins, you still wouldn't be able to guarantee that you were detecting a second tab correctly. For example, maybe I have one window open, then close it. Now I open a new window. You would likely detect that as a second tab, even though I already closed the first one. Now your user can't access the first window because they closed it, and they can't access the second window because you're denying them.
In fact, my bank's online system tries real hard to do #2, and the situation described above happens all the time. I usually have to wait until the server-side session expires before I can use the banking system again.
You can't prevent the user from refreshing, nor should you really be trying. You should go back to why you need this solution, what's the root problem here?. Start there and find a different way to go about solving the problem. Perhaps is you elaborated on why you think you need to do this it would help in finding such a solution.
Breaking fundamental browser features is never a good idea, over 99.999999999% of the internet works and refreshes with F5, this is an expectation of the user, one you shouldn't break.
Although its not a good idea to disable F5 key you can do it in JQuery as below.
<script type="text/javascript">
function disableF5(e) { if ((e.which || e.keyCode) == 116 || (e.which || e.keyCode) == 82) e.preventDefault(); };
$(document).ready(function(){
$(document).on("keydown", disableF5);
});
</script>
Hope this will help!
Back in the ole days of CGI we had many forms that would trigger various backend actions. Such as text notifications to groups, print jobs, farming of data, etc.
If the user was on a page that was saying "Please wait... Performing some HUGE job that could take some time.". They were more likely to hit REFRESH and this would be BAD!
WHY? Because it would trigger more slow jobs and eventually bog down the whole thing.
The solution?
Allow them to do their form.
When they submit their form... Start your job and then direct them to another page that tells them to wait.
Where the page in the middle actually held the form data that was needed to start the job.
The WAIT page however contains a javascript history destroy. So they can RELOAD that wait page all they want and it will never trigger the original job to start in the background as that WAIT page only contains the form data needed for the WAIT itself.
Hope that makes sense.
The history destroy function also prevented them from clicking BACK and then refreshing as well.
It was very seamless and worked great for MANY MANY years until the non-profit was wound down.
Example:
FORM ENTRY - Collect all their info and when submitted, this triggers your backend job.
RESPONSE from form entry - Returns HTML that performs a redirect to your static wait page and/or POST/GET to another form (the WAIT page).
WAIT PAGE - Only contains FORM data related to wait page as well as javascript to destroy the most recent history. Like (-1 OR -2) to only destroy the most recent pages, but still allows them to go back to their original FORM entry page.
Once they are at your WAIT page, they can click REFRESH as much as they want and it will never spawn the original FORM job on the backend. Instead, your WAIT page should embrace a META timed refresh itself so it can always check on the status of their job. When their job is completed, they are redirected away from the wait page to whereever you wish.
If they do manually REFRESH... They are simply adding one more check of their job status in there.
Hope that helps. Good luck.
No, there isn't.
I'm pretty sure there is no way to intercept a click on the refresh button from JS, and even if there was, JS can be turned off.
You should probably step back from your X (preventing refreshing) and find a different solution to Y (whatever that might be).
Issue #2 now can be solved using BroadcastAPI.
At the moment it's only available in Chrome, Firefox, and Opera.
var bc = new BroadcastChannel('test_channel');
bc.onmessage = function (ev) {
if(ev.data && ev.data.url===window.location.href){
alert('You cannot open the same page in 2 tabs');
}
}
bc.postMessage(window.location.href);
Number (2) is possible by using a socket implementation (like websocket, socket.io, etc.) with a custom heartbeat for each session the user is engaged in. If a user attempts to open another window, you have a javascript handler check with the server if it's ok, and then respond with an error messages.
However, a better solution is to synchronize the two sessions if possible like in google docs.