Bit of background in the problem: I am working on a project that loads most of it's content via api calls in JS. The initial page is built in PHP and delivered ready to use, but every interaction/load after that is just done in JS async and pushed to the "content area" of the html. I'm adding QoL so that you can navigate back to where you were using your history/back/forward button, but in order to do that, every time you navigate using those buttons, I would like to force-refresh the page (for various reasons which I don't think are relevant but am happy to describe if requested).
I'm struggling to understand both pushState and pageShow when used in conjunction. As far as I know, I can use pushState to push new entries to the history object every time it's run, like so:
// Update history
var stateObj = {};
history.pushState(stateObj, response.data.title, uri);
That seems to be working when I run that section of code and check my browser history; a nice neat entry sitting there every time I run it. As far as I know, the title isn't actually supported by any browser, but it doesn't hurt to have it.
My issue occurs when I try to use that newly generated history with the back/forward buttons. As far as I can tell doing some google research, typical browser behavior will not actually reload the page when I press the back button. Herein is where I believe my problem occurs. While navigating to any url fresh will load that specific piece of content into the content area, the site is basically a single page application, loading content into the content area async as it needs it. It doesn't actually change pages. I'm not sure, but I think that is the core problem. I have tried to use several events to "catch" the back/forward behavior:
window.onunload
window.onpageshow
$(window).on("pagehide", function() {})
window.addEventListener("pageshow", function(event) {})
I know several of those are basically the same thing, but I was trying to cover my bases. I have looked around for a solution, and I know that window.onunload is SUPPOSED to override the bfcache (not even sure if that is my problem), but it doesn't seem to fire at all, no matter how many times I navigate between the history.pushState entries. I'm not familiar enough with any of these functions to tell where my problem is. What am I doing wrong?
Related
Posting without a target so that a web page reloads seems useful behaviour for some things - such as writing a login page. I have implemented a calendar in PHP which takes advantage of this. It reloads an object from the session (or creates a new one if not present), applying any changes that result from the post then saves the object back to the session. The problem is this. If I hit the back button I don't want to go back through every click of the calendar button but would rather jump back to the page before arriving at the calendar page. Not only that, if I do go back one calendar page after another I get an annoying "confirm form resubmission". I have implemented an incrementing value after the # for each post so that I might be able to use window.onhashchange. The problem is that window.onhashchange never fires so I am unable to intercept the back button and pop the history stack. Any ideas? Am I better off coding on the server side with javascript?
Well I solved one problem. My form subclass in PHP defaults to using POST as I understand this is more secure. This causes the annoying resubmission problem when using the back button. I now use GET in my calendar page which solves this issue. I am still bemused by JS debugging in Netbeans. I have never got script to stop on a breakpoint within a single document. I have previously had it working with an external javascript source but this no longer works. If I can output to console but there is no window in which to see the output. I am told window.alert no longer works for some events in Chrome. I am completely blind! To add to the irritation, it took me a while to realize was that the javascript file was cached and changes would not be reflected in behaviour. I have put a random number into the script tag which fixes this issue. As I am debugging using netbeans connector in Chrome I have no idea why this does not force the js file to refresh. All in all, this appears to be a pretty shambolic toolchain.
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 was browsing thought GitHub today and noticed that the individual repository navigation doesn't use hash-bangs in the URL /#! or /# and the back button still works. How do you think they are accomplishing this? How does this affect search engine crawling from Googlebot? I know it looks for # in the url.
I'm really quite curious as I know using /# is quite debatable.
Here's an example: https://github.com/mirah/pindah
Thanks!
They blogged about it a while back:
https://github.com/blog/760-the-tree-slider
The effect is implemented history.pushState() function and handlers on the popstate event — both a part of the HTML5 DOM interface in some browsers.
Clicking the link uses pushState() to update the location and load new data into the page without reloading the whole page. Handling popstate makes the back button work correctly.
The GutHub blog calls their particular usage the “Tree Slider” (it loads the content for tree members and visually slides it into place). The effect and its implementation was described on the GitHub blog.
A website contains a "random" link, which loads a url that returns a 307 redirecting to the url we want. It works fine: click it and you load a random page. The problem is that each time you click it, the browser assumes you're loading the same page: so if you're on the homepage, then you follow the random link 5 times, then you press back, you'll be taken all the way back to the homepage, with no way to find the random pages you were just looking at. I want to modify this behavior so that users can access previous random pages via the back and forward buttons.
I don't own the website, so I can't just change the redirect code.
Here's what I've tried, all of which has failed.
Predicting what would be redirected to. While somewhat possible, there would be no way to avoid failure in up to .1% of clicks, and it would react very poorly to unexpected events, like a page that's published a day late, let alone a sit structure change.
Loading the 307 page via ajax. The request stops at readystate == 2 and I can't access the location header.
Cancel the click event and instead set location.href = random_link.href. This has no effect - the new page still doesn't go into history.
Have the new page call history.pushState. This successfully adds the page to history, but I can't find a way to distinguish between new pages and ones being opened via the back button, so the history quickly becomes very corrupted.
Keeping my own history in localStorage. As above, I can't tell when the back button is being used.
I'm working on a solution that I'm pretty sure will work, involving loading the page in an iframe over the existing page and using a background process and messaging to work around the fact that content injections from chrome extensions can't access window.parent from within iframes. And using the history API to reflect the current iframe's URL in the address bar, and get the back and forwards buttons to apply to the current iframe where appropriate.
While I'm pretty sure the last solution can be made to work, it's a hideously complex and heavyweight approach to what seems like a simple problem. So I thought I'd ask you guys before I continue: any other ideas?
Have you tried storing the locations in localStorage, then hi-jacking the back button ?
I am sure you know how localStorage works, for hi-jacking the back button you can refer to this : Is there a way to catch the back button event in javascript?
T.
i want to know is there any way we can know browser's events.. like : clicking on BACK button, FORWARD button, REFRESH button by javascript.
These specific browser events are not available as it would be vulnerable to severe privacy violations. Privacy is something browser vendors hold sacred and a key selling (proverbial) point. All browsers allow you to know is when a user enters or leaves your page for which Kamui pointed out the technical details.
Within the same site, it's possible to achieve some browser event tracking using cookies and javascript. For example track wether users click on a hyperlink and label it as a forward event and when a user leaves the page without clicking on a hyperlink it could be one of:
browser url input
back action
javascript location.href replace
The location.href replace can be tracked as well when you have full control over all javascript, just use a helper method with tracking code instead of directly chaning location.href.
That leaves browser url input and the back action. With cookies and request headers (getting the referrer) it is possible to get close to finding out the forward and back events, though not 100%, but pragmatically, 99% sure is good enough.
Figuring out the refresh event is easy with request headers (referrer), if the current url matches the referrrer, it's a refresh event.
Now I offer no code or definite solution, but I outlined what you could do to track back, forward and refresh events within a single domain context. It won't be a quick and easy way to implement it and as far as I know, there's no framework in existance that reliably tracks browser events or even comes close to what I described above.
A more common/lazy technique to achieve something similar is to create a single page app, for which there are many frameworks available. Just google single page app framework, but thats a pretty heavy solution with other implications that I won't go into now.
You can not capture (for example run some piece of code when user presses Back button) them, however, you can direct your pages in history by using:
history.go
history.back
history.forward
More about JS History object.
As #sarfraz says you cannot capture the back and forward button clicks but you could call
window.onbeforeunload = function(){alert("you just tried to leave the page");};
which should be triggered when either the back/forward/refresh buttons are clicked to perform an action, unfortunately you can't tell if they are going back or forward. Please note don't alert a message it's really annoying when trying to exit a page.
EDIT
you can also do this in jQuery if you have it
$(window).unload( function () { alert("Bye now!"); } );