In the following code (JSFiddle here):
<form>
<button>ok</button>
</form>
$(function(){
$('form').submit(false) ;
$('button').click(function(){ $('form').remove() }) ;
}) ;
When you click the button in Google Chrome 48, it triggers a form submission.
If you do it in Firefox 43, however, there is no form submission.
It seems to me that the Firefox behavior should be the correct one, but since I don't have such a deep knowledge of the standard, I don't really know.
Is either behavior wrong or buggy?
Follow up:
I just found out that the same test case but without using jQuery doesn't trigger a form submission in neither browser.
<form onsubmit="return false">
<button onclick="form.remove()">ok</button>
</form>
This could not be a timing issue because there's no thread concurrency in Javascript. Event threads will always run in sequence, so the button
event handler must finish before the form
event handler starts.
I'm blind here. jQuery must be doing some weird cumbersome stuff for this to happen in Chrome.
Follow up 2:
It's not a jQuery problem. At the jQuery bug tracker I was told that inline event handlers don't follow the same specification as those attached with addEventListener
, so a true functionally equivalent code should be like this:
<form>
<button>ok</button>
</form>
<script>
document.querySelector('form').addEventListener('submit',function(){ return false }) ;
document.querySelector('button').addEventListener('click',function(evt){ evt.target.form.remove() }) ;
</script>
And this does behave like the jQuery version.
Your first code adds a returnFalse
jQuery event listener:
$('form').submit(false);
In a jQuery event listener, return false
is equivalent to
event.stopPropagation();
event.preventDefault();
The later should prevent the submission of the form.
However, before the submit
event is fired, you use $.fn.remove
. This not only removes the form from the document, it also cleans its jQuery data, including the event listener.
Therefore, when the browser fires the submit
event to the form, it is not canceled.
Then browsers behave differently (demo):
If you don't want to remove jQuery data, you should remove the form using vanilla-js methods instead of $.fn.remove
.
In your second code, you cancel the event in a vanilla-js event handler.
Since it's not jQuery data, $.fn.remove
does not remove it, so the submit
event is canceled and the form is not submitted.
In your third code, you you remove the form using vanilla-js methods, so its jQuery data is not cleaned.
This does not matter because the submit
event listener is added with vanilla-js too.
However, the event is not canceled. That's because, unlike vanilla-js event handlers and jQuery event listeners, the value returned in a vanilla-js event listener is completely ignored.
So at the end the result is the same than in the first code, but they are not equivalent.
If you want to cancel an event using a vanilla-js event listener, you should use
event.preventDefault();
This would make it behave like the second code.