Reputation: 103
I want to fire and forget a request, with a short grace time, when user clicks a link or submits a form. Here's a simplified code that I'm using:
element.addEventListener(eventType, function(event) {
if (event.retriggered) {
return true;
}
let target = event.target;
let newEvent = new event.constructor(event.type, event);
newEvent.retriggered = true;
setTimeout(() => {
target.dispatchEvent(newEvent);
}, 250);
// fire and forget the request
makeRequest();
event.preventDefault();
return false;
});
This works fine for click
events and it works fine for submit
event in Firefox but not in Chrome. I've created a fiddle here. In Firefox, if you click the button, you can see that the browser makes a GET request, but that does not happen in Chrome. According to my tests the original and new event look the same in both browsers and dispatchEvent
returns true
. Still, the actual submit is not triggered in Chrome, so I'm wondering is Chrome stopping the submit as a security measure or did I miss something?
Upvotes: 2
Views: 422
Reputation: 2351
The event you are dispatching is at least a little different from the event you're trying to copy. Your event has the isTrusted
property of the event set to false
. Perhaps this is the reason why Chrome doesn't submit the form.
What I do know is how you can your desired result, for forms, with slightly different code. I've based this on the code in your Fiddle so it now handles just the form submit.
let
form = document.getElementById('form');
form.addEventListener('submit', function(event) {
setTimeout(() => {
form.submit();
}, 250);
event.preventDefault();
});
<form id="form" method="get" action="/echo/html/">
<button type="submit">Go</button>
</form>
Instead of dispatching the submit event yourself, you can just call the submit()
method of the form. This will submit the form but doesn't cause any submit handlers to be fired (as per this MDN article). It will save you the check in the handler to see if the submit should be delayed or not.
You could adjust it to also work with anchors.
let
form = document.getElementById('form'),
anchor = document.getElementById('anchor');
function onDelayNavigationEvent(event) {
const
target = event.target;
if (target.hasAttribute('is-delayed')) {
return true;
}
setTimeout(() => {
if (target.tagName.toLowerCase() === 'form') {
target.submit();
} else {
target.click();
}
}, 2000);
target.setAttribute('is-delayed', true);
event.preventDefault();
}
function delayNavigation(element, eventName) {
element.addEventListener(eventName, onDelayNavigationEvent);
}
delayNavigation(form, 'submit');
delayNavigation(anchor, 'click');
<form id="form" method="get" action="/echo/html/">
<button type="submit">Go</button>
</form>
<a id="anchor" href="//stackoverflow.com">Stack Overflow</a>
Upvotes: 1