My website, as most websites today, uses the same template for most of its pages and I am building a system that allows for ajax to load only page content without reloading the whole template. For the purpose I'm looking for a method that fires before the browser is redirected to another page. Something like onbeforeunload but I also need to know the location of the redirect, is there such a thing?
I need to catch link clicks, back button clicks, forward button clicks as well as manual redirects like window.location = url
There is no direct way to find out what URL the user is leaving the page for.
You would need to bind event handlers to the various different things that the user can use to leave the current page.
For links, you can bind a click event handler and then examine the href attribute.
For forms, you can bind a submit event handler and then collect the form data and examine the action and method.
For the back button you can bind a popstate event handler (which you could use in conjunction with pushState and friends).
You, obviously, couldn't detect where the user was going if they used a bookmark or just typed a new address into the address bar.
Related
I have forms in my application, all in one page, and I change them on button click without refreshing page.
How can I secure the form in such a way that if someone navigates away, change form or closes the browser tab, they should be prompted to to confirm they really want to leave the form with unsaved data?
Yes I know about onbeforeunload event, but it wouldn't work if I change form without refreshing page
Hope someone understand me, and can help with an advice
P.S. I work with svelte
Whether there was a navigation or not is irrelevant, you just have to react to changes, e.g. you can handle a change event on the form-level to add the beforeunload handler which adds the confirmation question.
Something like:
<script>
function onChange() {
window.addEventListener('beforeunload', e => {
e.preventDefault()
return e.returnValue = "Are you sure you want to exit?";
});
}
</script>
<form on:change={onChange}>
...
</form>
(Maybe add a flag & if to prevent adding duplicate listeners.)
The change event only captures common interactions with native input elements. If the event is stopped from reaching the form (or whatever container you add the listener on) this will not work. It will also not capture more complex logic, like adding an item to some list.
Depending on your concrete code, you may need to handle additional/different events or changes.
If you use a client-side router of some kind you also have to signal to it, that it should not navigate away because beforeunload will not be triggered. How this is done depends entirely on the router being used.
I'm building a little CoffeeScript application with 10 buttons and a container (simple). When the user press on one of the button : the container change.
The buttons look like a navbar and instead of using links (that will reload the entire page), I used javascript (Coffeescript, jquery or whatever) to change the content of the page (with some Ajax query to load data).
The problem is that the back and forward button of the browser can't work with that solution... and I need to find a solution for that. Routing maybe ?
I really like the way Asana.com resolved this issue: actually the address change but the content seems not to be entirely reloaded.
What do you suggest ? Thanks for the help
Hashes. The simplest solution is to define an URL hash every time the user clicks on a button. For example:
location.href = "#" + button.id;
With that, you create a history entry, and the user can press back or forward in the browser.
But how can you check when this happens? There's the hashchange event:
window.onhashchange = function() {
var state = location.hash.substring(1); // chomps the initial #
...
};
Basing your code on the state variable, you can trigger your AJAX calls from there.
By the way, you can change your code altogether, using links instead of buttons with an hash as the href property, which does not reload the page, but creates an history entry and fires the hashchange event.
The hashchange event is supported by every modern browser (that support history.pushState too, a more flexible and powerful way to control your history) and IE8-9.
I have a webpage which has various "internal" links on it to various objects with various ids.
The webpage also has an attachment to the scroll event to hide / display certain items when scrolled by a certain amount.
I'd like to trigger the scroll event handler when the page navigates to another section after clicking on one of these links.
The click event is fired before navigation so I can't attach to that, as it needs to make decisions based on the new location.
How about the hashchange event? It's widely supported these days. (Modernizr has a test and lot's of polyfills, just in case...)
BTW, if you want to save the locations check out the HTML5 History API. history.pushState should do the trick.
There is no "onChange" event being fired when you click on a hash link on a single page. The only way contemporary (AJAXed) pages monitor hash change is using an interval after which a JavaScript function is called to do that check.
So in other words, the only possibility is to save last hash location (document.location.hash) on timely basis and navigate back to the old location if some condition is not met.
I'm creating an HTML and Javascript client for running in browser which talks to REST API. I'm using RouteMap to set my URLs. So I've kept a convention something like this
http://mysite.com/#/{ResourceName}/[edit|view|list]/[Id]/
I've set just one route and I'm grabbing these parameters in the function bounded to hashchange. Most of the things work fine. Just two issues and I'm stuck because of them.
If the user clicks on the same link twice, hashchange event doesn't fire. Yes, hash has not changed so obviously it won't fire. But there should be something which can be done and I'm missing that.
If I change something in the UI (like bring up new divs and hide some) for which I don't want to change the hash link, I loose that history and can't go back by clicking the back button properly.
Any help will be grateful.
For #1, you probably want to attach a handler to the link click event. That way you can tell if the link is being clicked. When I use onhashchange, I always attach something to the click event to assist polyfills for onhashchange, so at least I can tell when it's failing.
For #2, I want to point out that having automatic stuff change the user's history is problematic. You could fill someone's history with minute, meaningless hash changes. I recommend only changing the history when the user actually interacts. Short of that, HTML5 does offer pushState and popState. Reference
I'm currently struggling with a good navigation on a website using Ajax calls and unobstrusive JS. I'm catching the click event on links, load the content, attach it to a div and then return false. This works quite well and also allows Google to crawl the site with speaky URLs.
But I didn't know how to deal with the browser back button. I found this solution to catch the event when the user clicks on the back button:
http://www.bajb.net/2010/02/browser-back-button-detection/
It works quite well. But I also want the back button to work normally when the user found the website via a link and wants to return to the previous page (I don't want to trap anyone).
When I thought about it the best way would be to use anchors. The normal back button supports them and you can go back in history without reloading the page (/#1 <- /#2 <- /#3 etc.)
It would work like this:
Use normal URLs in the link, but catch the click event
When user clicks, load content and attach it to a DIV
Change the window.location, using an anchor (e.g. 'domain.com/#products/women-clothing' with window.location="#products/women-clothing";)
When the window.location changes, get the anchor, read out the path and get the content via ajax, attach it to a DIV
Only the last part isn't really clear for me and I could need help here.
Finaly, my question: Does this make any sense?
Thanks!
Just add the href to window.location.hash after loading the content into a div. Then you can use that back button detection script to load what ever is in the hash.
I solved the problem by using this great jQuery Plugin: History.js
Thanks!