I am trying to remove event using window.removeEventListener which I have added using window.addEventListener for event beforeunload but it is not getting removed. I am trying following code
addAlertWithListener(){
window.addEventListener('beforeunload', (event) => {
// Cancel the event as stated by the standard.
event.preventDefault();
// Chrome requires returnValue to be set.
event.returnValue = 'You are currently in edit mode. Are you sure you want to refresh the page?';
},true);
}
It is being added but when I am trying to remove the same function using below code :
removeAlertWithListener() {
window.removeEventListener('beforeunload', null,true);
}
It still gives alert message. Am I missing something over here? I tried with and without last param. None of the thing seems working here.
addEventListener and removeEventListener are implemented in a weird way in JavaScript, they need exactly the same parameters in order to retrieve the registered listeners. That's different from, like, setTimeout where an id is returned.
In Angular, usually I do something like this:
private readonly BEFORE_UNLOAD_PARAMS = ['beforeunload', (event) => ..., true];
private isBeforeUnloadActive: boolean = false;
addAlertWithListener() {
if (this.isBeforeUnloadActive) return;
window.addEventListener(...this.BEFORE_UNLOAD_PARAMS);
this.isBeforeUnloadActive = true;
}
removeAlertWithListener() {
window.removeEventListener(...this.BEFORE_UNLOAD_PARAMS);
this.isBeforeUnloadActive = false;
}
The flag will prevent the listener to be registered twice
Related
Hi I want to know how to prompt a message on browser tab close.
I am using Reactjs.
handleWindowClose(){
alert("Alerted Browser Close");
},
componentDidMount: function() {
window.addEventListener('onbeforeunload', this.handleWindowClose);
},
componentWillUnmount: function() {
window.removeEventListener('onbeforeunload', this.handleWindowClose);
}
this is what I have tried adding to my react component.Please guide me on how to proceed further.
What you did is correct apart from the event name and the fact that alert will be blocked in that particular event.
You can show a message like this:
window.addEventListener("beforeunload", (ev) =>
{
ev.preventDefault();
return ev.returnValue = 'Are you sure you want to close?';
});
Hope this helps.
Amid's answer worked well for me.
The way I used it:
class MyComponent extends Component {
// Things to do before unloading/closing the tab
doSomethingBeforeUnload = () => {
// Do something
}
// Setup the `beforeunload` event listener
setupBeforeUnloadListener = () => {
window.addEventListener("beforeunload", (ev) => {
ev.preventDefault();
return this.doSomethingBeforeUnload();
});
};
componentDidMount() {
// Activate the event listener
this.setupBeforeUnloadListener();
}
// Render method.
render() {
return (
<div>My component</div>
)
}
}
I needed to fire logic after the user decided to close the tab.
Here is my solution (for functional react components & TypeScript):
useEffect(() => {
window.addEventListener('beforeunload', alertUser)
window.addEventListener('unload', handleTabClosing)
return () => {
window.removeEventListener('beforeunload', alertUser)
window.removeEventListener('unload', handleTabClosing)
}
})
const handleTabClosing = () => {
removePlayerFromGame()
}
const alertUser = (event:any) => {
event.preventDefault()
event.returnValue = ''
}
alertUser warns the user with the default browser dialog.
handleTabClosing is fired when the user chooses to close the tab.
I have derived my solution from this blog post from Mike Pottebaum
One can use hooks now to implement the same. e.g.
import { useBeforeunload } from 'react-beforeunload';
and then in your component use:
useBeforeunload(() => "Are you sure to close this tab?");
Though we are returning custom string, it will show browser's default message here.
If you want to display a sort of confirmation before leaving the page then follow the beforeunload event guidelines:
According to the specification, to show the confirmation dialog an
event handler should call preventDefault() on the event.
However note that not all browsers support this method, and some
instead require the event handler to implement one of two legacy
methods:
assigning a string to the event's returnValue property
returning a string from the event handler.
To combat unwanted pop-ups, browsers may not display prompts created
in beforeunload event handlers unless the page has been interacted
with, or may even not display them at all.
The HTML specification states that calls to window.alert(),
window.confirm(), and window.prompt() methods may be ignored during
this event. See the HTML specification for more details.
This should cover most cases. Use a mounting useEffect to define the callback, add the event listener, and return the cleanup function to remove the listener.
useEffect(() => {
const unloadCallback = (event) => {
event.preventDefault();
event.returnValue = "";
return "";
};
window.addEventListener("beforeunload", unloadCallback);
return () => window.removeEventListener("beforeunload", unloadCallback);
}, []);
You can show on unmounting component but you can't show a custom message on window close. Modern browser doesn't support it (Check browser compatibility). You can set an alert on a click event and there you can set some custom message.
Thank you
I'm trying to use the function window.addEventListener('beforeunload', function (event) {...}
In the function, I want to know which action triggered the listener.
I tried to use this method with no success:
window.addEventListener('beforeunload', function (event) {
if (performance.navigation.type == 1) {
document.write('Window was refreshed!');
}
else {
document.write('Window was closed!');
}
});
Any action (refresh/close/'go back') triggers the else part... what am I doing wrong?
Alternative method would be appreciated as well.
Well, you always trigger the else handler, because of the way peformance.navigation works.
Even if you write it in the beforeunload handler, it still runs on your current document, not the one you are loading, so it will output the PerformanceNavigation object that contains info on how you opened your current page, and not the one you are trying to navigate to.
As to the part in your question about deteciting whatever method user used to leave the page, i don't think thats possible at the moment, not without usage of 'dirty' hacks/workarounds (detecting which button has user clicked, detecting keyboard events, etc.)
use router events You can subscribe in your app.component like
ngOnInit() {
this.router.events
.subscribe((event) => {
// example: NavigationStart, RoutesRecognized, NavigationEnd
console.log(event);
});
}
I'm not sure how to word it, this is what I'm trying to accomplish:
$(document).on('click', '.my-element', function(e) {
var data = [{
'event': e,
'self': this
}];
// Trigger the override function first in case they need to stop prop
$(document).trigger('override:something',dataa);
// Would like to only trigger this default method if the event above is not set
$(document).trigger('something',data);
});
Then on another page I have something to catch this event, like so:
$(document).on('override:something', function(e,data) {
e.stopImmediatePropagation();
data.e.stopImmediatePropagation(); // neither work
});
If I could stop all subsequent events like this that would be optimal, but I could also make it work if there were a way to check if custom events are set.
I could check whether override:something exists and if it does, do not execute the default something event afterwards.
I've tried setting removing specific callbacks like this, but it did not perform as expected and could get hard to manage.
var mycb = function() {
alert('hi');
}
$(document).on('something', mycb);
// now to remove it
$(document).off('something', mycb); // does not remove the event
Any help is greatly appreciated.
Thanks for the help guys, but this solution seems to the only thing I've found to work for now. Still accepting alternate answers, though.
var override = jQuery._data($(document)[0], 'events')['override:something'];
$(document).trigger('override:something', data);
if ( typeof override == typeof undefined )
$(document).trigger('dashboard:friend', data);
How can I get the sender of an onSubmit event in any browser? Or at least in FF and IE?
Esp. as event.srcElementin IE seems to be the target?
Well, isn't there anything like explicitOriginaltarget in browsers other than FF?
I'm looking for any solution in pure javascript, no JQuery.
What I want to do:
I've got a form. And depending on the sender I want to do differnt actions in the onSubmit(event) routine.
What I got in my init function:
var top_most_form = document.getElementById("upper_menu_form");
top_most_form.onsubmit=function(event){
var target = <apparently magical things have to happen here>;
if ("upper_menu_form" == target.id) {
AddSpinner();
AddStarttimeToForm();
AddThruputToUpperForm();
} else {
return false;
}
Here you have a function. You just need to evaluate wich parameter is present in your event object
function getTarget(e){
e=e||window.event;
return (e.target||e.srcElement);
};
See: jQuery - how to determine which link was clicked
How can I use addEventListener() to assign a handler to an HTML form's Submit button, similar to assignment to the button's 'onclick' attribute, without triggering the form's default submit() behavior?
I have no trouble assigning a custom function to the 'onclick' attribute of the "Submit" button. The custom function executes a variety of steps, then creates an Ajax request object and uses this to send the data to the server. The default submit() behavior isn't triggered.
submitButton.onclick = function() {
mySubmit();
return false;
};
function mySubmit() {
//do stuff
notTheDefaultUrl = generateNonStandardUrl();
request = GetStandardAjaxRequestThingamabob();
request.open("POST", notTheDefaultUrl, true);
request.onreadystatechange = myHandler;
request.send(formData);
return false;
}
But with addEventListener(), the browser submit the request twice -- once under the Ajax request object, and again with the default HTML form submit() behavior. (I can tell b/c the mySubmit function sends the data to a different URL than the default -- but both the default and the Ajax url are appearing in the server logs.)
var func = window['mySubmit'];
submitButton.addEventListener('click', func, false);
I'm aware that the function assigned to the button must return 'false' to prevent triggering the default submit() behavior. I thought mySubmit() did that, and I've tried to write the function passed in via addEventListener to return false more explicitly (instead of 'func', 'function() {mySubmit(); return false}') but these dosn't work either.
So how do I do this?
UPDATE
Comments to Peter's raised some browser compatability issues; also, IE doesn't support addEventListener(). This code addresses these. I've tested it in Firefox and IE 8.
function func( event ) {
if ( event.preventDefault ) { event.preventDefault()};
event.returnValue = false;
// do whatever
}
if (submitButton.addEventListener) {
submitButton.addEventListener('click', func, false);
}
else {
submitButton.attachEvent('onclick', func);
}
Apologies for the messy newbie formatting.
You need to receive the event in your handler function, and prevent the event from executing its default behavior. This applies to click events, submit events - really any event that's cancelable.
// using your example
submitButton.addEventListener('click', func, false);
// here's what func should look like
function func( event )
{
if ( event.preventDefault ) event.preventDefault();
event.returnValue = false;
// do whatever
}
Shouldn't the handler be added as event listner for "submit" event?
It makes sense the "click" event handler returning false does not prevent default submit behavior, I think. It makes sense, kind of, that the form gets submitted to both targets.
edit: added second paragraph.
comment: And as Ken says the event listener should be added to the form and not the button.
edit 2: So I was wrong. You shouldn't use "return false;" but something like...
event.preventDefault ? event.preventDefault() : event.returnValue = false;
EASY WAY: Set the forms onsubmit attribute to return false
<form onsubmit="return false;">
Now if it MUST be done through assigning of an event listener through javascript, then the answer given by Peter Bailey is ideal.
My form validator does exactly what your trying to do. Check out this example
http://murdog05.github.com/yui3-gallery/examples/json/beforeSubmitExample.html
And the code base
http://yuilibrary.com/gallery/show/formvalidator
You might find it handy.