Javascript preventDefault() ignored on second submission - javascript

I'm experiencing some issues preventing form submission when I try to submit an invalid situation.
Assume I have the following code:
window.onload = function(){
$("form").on("submit",function (event) {
$("#errorDiv").fadeOut(null, null, function () {
OnSubmitForm(event)
});
})
}
function OnSubmitForm(event) {
let items = $("#mytable").dxDataGrid("instance").getSelectedRowsData();
if (items.length == 0) {
event.preventDefault();
} else if (items.some(item => item.booleanProperty != true)) {
event.preventDefault();
let badItems = items.filter(item => item.booleanProperty != true).map(item => item.id);
let divText = "<strong>bad items:<br>"
+ badItems.join("<br>") +"</strong>";
$("#errorDiv").html(divText);
$("#errorDiv").fadeIn();
}
}
My intention is to fadeOut the div I use to display the error, and when the animation is complete I call OnSubmitForm, passing event to it.
The flow of my actions is the following:
I click the submit button
fadeOut kicks in
OnSubmitForm is called
the else if condition is true, so the block is executed
event.preventDefault() works
I click again the submit button
Form is submitted
What's happening?
Plus, I've noted that the result of event.isPreventedByDefault() returns false before the first event.preventDefault(), then it returns true, because the event was already prevented once, according to the MDN documentation.
More info
I forgot to mention that if I do the same violating the first "rule" (first if statement) everything works as expected.

You call OnSubmitForm when the fade out is complete. This happens after the submit event handler function has finished without preventing the default behaviour.
The form has already been submitted by the time you try to stop it.

Related

Form submits despite preventDefault() because of a different EventListener

I have two EventListeners, one to handle a form and the other for 'Add to Cart' buttons. When the events are fired, a post request is sent to the server which handles the according data, so i need the form to not be submitted but be handled by the server instead.
Before implementing the EventListeners which handles the 'Add to cart' buttons, the form was working as intended with the use of event.preventDefault();. With the buttons' EventListener however the form now submits and directs me to /login. I have tried every solution I found, I used .stopPropagation(), .preventDefault() and return=false; to both listeners, I changed the buttons to div elements. However the form is not working as intended unless I completely remove the second EventListener.
I would go on replacing the form element with a div but it needs to stay as an HTML form, so I have to work out a solution to this.
I'm including the code below, thanks in advance:
window.onload =function formSubmit(){
const form = document.getElementById('login-form');
form.addEventListener('submit', event => {
event.preventDefault(); // prevent the form from submitting
const username = form.elements.username.value;
const password = form.elements.password.value;
login(username, password);
});
}
//addbuttons are added dynamically after the other elements are already loaded so im putting a timeout for queryselector to gather them
setTimeout(window.onload =function productRequest(){
const purchaseBtns = document.querySelectorAll('.purchase-button');
purchaseBtns.forEach((btn) =>{
btn.addEventListener('click', () => {
var product_selected;
for(i in products){
if(products[i].id == btn.dataset.productId){
product_selected = products[i];
}
}
addToCart(product_selected);
});
});
}, 1000);
window.onload can store ONE function... No more.
Seems like the first one fires... And not the second because at that point, the load event already fired (before the second assignement overwrote the first, that is after the first timeout).
So try with one load event listener:
document.addEventListener("load", function(){
// Form's event listener
const form = document.getElementById('login-form');
form.addEventListener('submit', event => {
event.preventDefault(); // prevent the form from submitting
const username = form.elements.username.value;
const password = form.elements.password.value;
login(username, password);
});
// Buttons event listeners setting 1 second after page load
setTimeout(() => {
const purchaseBtns = document.querySelectorAll('.purchase-button');
purchaseBtns.forEach((btn) =>{
btn.addEventListener('click', (event) => {
// Prevent the event from bubbling to the form if the buttons are inside it
event.stopPropagation()
// and obviously, also prevent submit
event.preventDefault();
var product_selected;
for(i in products){ // Hoping you have that products defined...
if(products[i].id == btn.dataset.productId){
product_selected = products[i];
}
}
addToCart(product_selected);
});
});
}, 1000)
}) // end of the load event handler

Chrome suggested box is not cleared after onsubmit

I submit a <form> in javascript with 'ENTER' key and call a function. This function returns false so that the page is not reloaded.
Unfortunately, the box is not cleared as shown in the picture.
the end of the list, but 'toto' and other entries were proposed. The suggestion box is not cleared.
How could I clear it?
Here is the code used
$('form').on('submit', function () {
var newUser = $('input.user').val()
displayPerson(newUser) // add the person
$('input.user').val('')
return false;
});
I would suggest to briefly remove the focus from the input:
$('form').on('submit', function () {
var newUser = $('input.user').val()
displayPerson(newUser) // add the person
$('input.user').val('').blur(); // <-- blur
setTimeout(function () { // Allow time for blur to happen
$('input.user').focus(); // <-- put focus back (if desired).
}, 0);
return false;
});

why "return false;" or "event.preDefualt();" doesn't work after $.post();?

why "return false;" or "event.preDefualt();" doesn't work after $.post();
Firstly,I simply written a return false after
$(#id).submit(function(e){ return false;}// it works properly.But
when i call something via $.post('check-email.php',{parameter},function{data}) and i try to write return false after that $.post call.It doesn't works and directly goes to next page.
here is my code:-
$(document).ready(function () { //newly added
$('#mysignupform').submit(function (event) {
return false;
or event.preDfault(); // only work here
var emailVal = $('#inputEmail').val(); // assuming this is a input text field
//alert(emailVal);
$.post('check-email.php', {
'email': emailVal
}, function (data) {
alert(data);
if (data == 'false') {
$("#mysignupform").submit(function (event) {
return false;
or event.preventDefault(); //both doesnt work here..why??
;
});
} else {
$("#mysingupform").submit(function () {
return false;
}); //retrun false doesnt work here..why??
}
});
});
});
I dont want to allow them to submit but still its happening. Please help me..!
Thanks in advance..
This should work:
$(document).ready(function () { //newly added
$('#mysignupform').submit(function (event) {
// your $.post call
$.post('check-email.php', {email: emailVal}, function (data) {
// ...
// having a return false means returning false to the success callback
// of your .post call. it is not the same as returning false to the
// submit() callback
});
// return false to submit()
return false;
});
});
Ajax works asynchronous. The easy solution is bind a click event handler on the submit button.
$('#your_submit_button').click(function (event) {
event.preventDefault();
var emailVal = $('#inputEmail').val(); // assuming this is a input text field
$.post('check-email.php', {
'email': emailVal
}, function (data) {
if (data !== 'false') {
// submit the form here
$("#mysingupform").submit();
}
});
});
Because $.post is asynchronous. Execution continues at the statement following the call to $.post immediately. Since there isn't a statement following it, the submit event handler function will simply return undefined and the browser will happily continue with the submit as if nothing happened.
The callback to asynchronous methods will only be executed some time later. In your case, that will be when the server returns a response. Since the outer function has already returned, there is nowhere for that callback function to return to.
You will need to always prevent the default action in a click event handler on the form submit button, and then re-submit the form programatically upon success in the $.post callback:
$('#mysignupform :submit').click(function (event) {
var form = this.closest("form"); // Get a reference to the containing form
event.preventDefault(); // Prevent the default action (form submission)
$.post('check-email.php', { /* data */ }, function (data) {
// If the data is good...
form.submit(); // Submit the containing form
});
});
Obviously you can't really do this if you're binding to the form submit event, since the re-submission of the form will trigger the event handler again and you'll be stuck in an infinite loop.
$.post(...) is asynchronous. Try $.ajax(async: false, ...) instead.
This is because the function that is executed after the post completes is executed asynchronously, i.e. you are no longer in the event handler.
This answer has a technique you can use - basically click the submit button again, after setting a Boolean flag to prevent your post logic from being executed twice.

Understanding event bubbling in Javascript

I've been trying to understand even bubbling, and not quite sure I completely follow it. I started reading about it so that I could warn users when they were leaving a page on my website if they had started to enter data into a form (in a similar way to Stack Overflow does!).
The following code seems to work cross-browser:
var entereddata = false;
$(document).ready(function()
{
$('#contactform').bind('keypress',function(e) {
if((e.which > 96 && e.which < 123) || (e.which > 47 && e.which < 58)) {
entereddata = true;
//alert(e.which);
}
});
});
function confirmLeave(e, d)
{
if(!e) e = window.event;//window.event;
if(!d) d = entereddata;
var confirmationMessage = 'It appears you have started to enter information into the contact form, but have not yet submitted it';
if(!d)
{
e.cancelBubble = true;
} else
{
return confirmationMessage;
}
}
window.onbeforeunload=confirmLeave;
However, this also gets called when I click the submit button for the form, which I don't want. I've tried various additions to the code, such as adding:
if($('#submit').click()){
submitted=true;
} else {
submitted=false;
}
and then changing if(!d) to if(!d && submitted==false) to the main code; however, this (and every other combination of trying to get the page to fire only if the submit button isn't clicked) doesn't work, with the warning either still showing when I click the submit button, or no warning being shown when anything is clicked!
This might boil down to the fact I don't understand the event bubbling process - I don't know why I need the e.cancelBubble = true; in the place I have it.
So, my two main problems are:
how do I check if the submit button is clicked, and only show the warning if it isn't clicked
and to understand eventBubbling; for example: if enteredData is true, then I'm not affecting the bubbling process. Should I be? Should I have e.cancelBubble=false if enteredData is false and e.cancelBubble=true if enteredData is true? What effect does setting the value of e.cancelBubble actually have when closing a page?
Am I also correct in thinking I don't need the event e.stopPropagation
at all, because Firefox supports event bubbling?
What about having such code?
$('#submit').click(function() {
entereddata = false;
});
This should be called before the actual form submission i.e. before confirmLeave is running, so lowering the flag should do the trick.
Try removing the onbeforeunload "listener":
$('#submit').click(function() {
window.onbeforeunload=null;
});
I don't think you need to worry about bubbling in this example...
return null if you want the browser to move on without asking the user, or return a string if you want the browser to show an alert asking the user if he wants to move on or not...
function confirmLeave(e) {
e = e || window.event;//window.event;
var confirmationMessage = 'It appears you have started to enter information into the contact form, but have not yet submitted it';
if(entereddata) {
return confirmationMessage;
} else {
return null;
}
}
Bubbling and propagation only applies to event's that should notify it's children or it's parents, and as far as i know window.onbeforeunload is a global event that will not be propagated.
Unrelated to bubbling, but you could bypass detecting whether keys were pressed and check the form data instead:
function hasNonemptyTextInputs() {
var textInputs = $('#contactform :input').filter(':text, textarea');
// Check for any field with a nonempty value
// .is() returns true iff the function returns true on any element
return textInputs.is(function() {
return $(this).val().length > 0;
});
}

ASP.NET Post-Back and window.onload

I got a function which checks if some input fields are changed:
var somethingchanged = false;
$(".container-box fieldset input").change(function() {
somethingchanged = true;
});
And a function which waits on window.onload and fires this:
window.onbeforeunload = function(e) {
if (somethingchanged) {
var message = "Fields have been edited without saving - continue?";
if (typeof e == "undefined") {
e = window.event;
}
if (e) {
e.returnValue = message;
}
return message;
}
}
But if I edit some of the fields and hit the save button, the event triggers, because there is a post-back and the fields have been edited. Is there anyway around this, so the event does not fire upon clicking the save button?
Thanks
When I do this pattern I have a showDirtyPrompt on the page. Then whenever an action occurs which I don't want to go through the dirty check I just set the variable to false. You can do this on the client side click event of the button.
The nice thing about this is that there might be other cases where you don't want to prompt, the user you might have other buttons which do other post backs for example. This way your dirty check function doesn't have to check several buttons, you flip the responsability around.
<input type="button" onclick="javascript:showDirtyPrompt=false;".../>
function unloadHandler()
{
if (showDirtyPrompt)
{
//have your regular logic run here
}
showDirtyPrompt=true;
}
Yes. Check to see that the button clicked is not the save button. So it could be something like
if ($this.id.not("savebuttonID")) {
trigger stuff
}

Categories