Intercept a form submit in JavaScript and prevent normal submission - javascript

There seems to be lots of info on how to submit a form using javascript, but I am looking for a solution to capture when a form has been submitted and intercept it in javascript.
HTML
<form>
<input type="text" name="in" value="some data" />
<button type="submit">Go</button>
</form>
When a user presses the submit button, I do not want the form to be submitted, but instead I would like a JavaScript function to be called.
function captureForm() {
// do some stuff with the values in the form
// stop form from being submitted
}
A quick hack would be to add an onclick function to the button but I do not like this solution... there are many ways to submit a form... e.g. pressing return while on an input, which this does not account for.
Ty

<form id="my-form">
<input type="text" name="in" value="some data" />
<button type="submit">Go</button>
</form>
In JS:
function processForm(e) {
if (e.preventDefault) e.preventDefault();
/* do what you want with the form */
// You must return false to prevent the default form behavior
return false;
}
var form = document.getElementById('my-form');
if (form.attachEvent) {
form.attachEvent("submit", processForm);
} else {
form.addEventListener("submit", processForm);
}
Edit: in my opinion, this approach is better than setting the onSubmit attribute on the form since it maintains separation of mark-up and functionality. But that's just my two cents.
Edit2: Updated my example to include preventDefault()

You cannot attach events before the elements you attach them to has loaded
It is recommended to use eventListeners - here one when the page loads and another when the form is submitted
This works since IE9:
Plain/Vanilla JS
// Should only be triggered on first page load
console.log('ho');
window.addEventListener("DOMContentLoaded", function() {
document.getElementById('my-form').addEventListener("submit", function(e) {
e.preventDefault(); // before the code
/* do what you want with the form */
// Should be triggered on form submit
console.log('hi');
})
});
<form id="my-form">
<input type="text" name="in" value="some data" />
<button type="submit">Go</button>
</form>
jQuery
// Should only be triggered on first page load
console.log('ho');
$(function() {
$('#my-form').on("submit", function(e) {
e.preventDefault(); // cancel the actual submit
/* do what you want with the form */
// Should be triggered on form submit
console.log('hi');
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<form id="my-form">
<input type="text" name="in" value="some data" />
<button type="submit">Go</button>
</form>
Not recommended but will work
If you do not need more than one event handler, you can use onload and onsubmit
// Should only be triggered on first page load
console.log('ho');
window.onload = function() {
document.getElementById('my-form').onsubmit = function() {
/* do what you want with the form */
// Should be triggered on form submit
console.log('hi');
// You must return false to prevent the default form behavior
return false;
}
}
<form id="my-form">
<input type="text" name="in" value="some data" />
<button type="submit">Go</button>
</form>

<form onSubmit="return captureForm()">
that should do. Make sure that your captureForm() method returns false.

Another option to handle all requests I used in my practice for cases when onload can't help is to handle javascript submit, html submit, ajax requests.
These code should be added in the top of body element to create listener before any form rendered and submitted.
In example I set hidden field to any form on page on its submission even if it happens before page load.
//Handles jquery, dojo, etc. ajax requests
(function (send) {
var token = $("meta[name='_csrf']").attr("content");
var header = $("meta[name='_csrf_header']").attr("content");
XMLHttpRequest.prototype.send = function (data) {
if (isNotEmptyString(token) && isNotEmptyString(header)) {
this.setRequestHeader(header, token);
}
send.call(this, data);
};
})(XMLHttpRequest.prototype.send);
//Handles javascript submit
(function (submit) {
HTMLFormElement.prototype.submit = function (data) {
var token = $("meta[name='_csrf']").attr("content");
var paramName = $("meta[name='_csrf_parameterName']").attr("content");
$('<input>').attr({
type: 'hidden',
name: paramName,
value: token
}).appendTo(this);
submit.call(this, data);
};
})(HTMLFormElement.prototype.submit);
//Handles html submit
document.body.addEventListener('submit', function (event) {
var token = $("meta[name='_csrf']").attr("content");
var paramName = $("meta[name='_csrf_parameterName']").attr("content");
$('<input>').attr({
type: 'hidden',
name: paramName,
value: token
}).appendTo(event.target);
}, false);

Use #Kristian Antonsen's answer, or you can use:
$('button').click(function() {
preventDefault();
captureForm();
});

Related

JS - Collecting data from one function to run in another [duplicate]

There seems to be lots of info on how to submit a form using javascript, but I am looking for a solution to capture when a form has been submitted and intercept it in javascript.
HTML
<form>
<input type="text" name="in" value="some data" />
<button type="submit">Go</button>
</form>
When a user presses the submit button, I do not want the form to be submitted, but instead I would like a JavaScript function to be called.
function captureForm() {
// do some stuff with the values in the form
// stop form from being submitted
}
A quick hack would be to add an onclick function to the button but I do not like this solution... there are many ways to submit a form... e.g. pressing return while on an input, which this does not account for.
Ty
<form id="my-form">
<input type="text" name="in" value="some data" />
<button type="submit">Go</button>
</form>
In JS:
function processForm(e) {
if (e.preventDefault) e.preventDefault();
/* do what you want with the form */
// You must return false to prevent the default form behavior
return false;
}
var form = document.getElementById('my-form');
if (form.attachEvent) {
form.attachEvent("submit", processForm);
} else {
form.addEventListener("submit", processForm);
}
Edit: in my opinion, this approach is better than setting the onSubmit attribute on the form since it maintains separation of mark-up and functionality. But that's just my two cents.
Edit2: Updated my example to include preventDefault()
You cannot attach events before the elements you attach them to has loaded
It is recommended to use eventListeners - here one when the page loads and another when the form is submitted
This works since IE9:
Plain/Vanilla JS
// Should only be triggered on first page load
console.log('ho');
window.addEventListener("DOMContentLoaded", function() {
document.getElementById('my-form').addEventListener("submit", function(e) {
e.preventDefault(); // before the code
/* do what you want with the form */
// Should be triggered on form submit
console.log('hi');
})
});
<form id="my-form">
<input type="text" name="in" value="some data" />
<button type="submit">Go</button>
</form>
jQuery
// Should only be triggered on first page load
console.log('ho');
$(function() {
$('#my-form').on("submit", function(e) {
e.preventDefault(); // cancel the actual submit
/* do what you want with the form */
// Should be triggered on form submit
console.log('hi');
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<form id="my-form">
<input type="text" name="in" value="some data" />
<button type="submit">Go</button>
</form>
Not recommended but will work
If you do not need more than one event handler, you can use onload and onsubmit
// Should only be triggered on first page load
console.log('ho');
window.onload = function() {
document.getElementById('my-form').onsubmit = function() {
/* do what you want with the form */
// Should be triggered on form submit
console.log('hi');
// You must return false to prevent the default form behavior
return false;
}
}
<form id="my-form">
<input type="text" name="in" value="some data" />
<button type="submit">Go</button>
</form>
<form onSubmit="return captureForm()">
that should do. Make sure that your captureForm() method returns false.
Another option to handle all requests I used in my practice for cases when onload can't help is to handle javascript submit, html submit, ajax requests.
These code should be added in the top of body element to create listener before any form rendered and submitted.
In example I set hidden field to any form on page on its submission even if it happens before page load.
//Handles jquery, dojo, etc. ajax requests
(function (send) {
var token = $("meta[name='_csrf']").attr("content");
var header = $("meta[name='_csrf_header']").attr("content");
XMLHttpRequest.prototype.send = function (data) {
if (isNotEmptyString(token) && isNotEmptyString(header)) {
this.setRequestHeader(header, token);
}
send.call(this, data);
};
})(XMLHttpRequest.prototype.send);
//Handles javascript submit
(function (submit) {
HTMLFormElement.prototype.submit = function (data) {
var token = $("meta[name='_csrf']").attr("content");
var paramName = $("meta[name='_csrf_parameterName']").attr("content");
$('<input>').attr({
type: 'hidden',
name: paramName,
value: token
}).appendTo(this);
submit.call(this, data);
};
})(HTMLFormElement.prototype.submit);
//Handles html submit
document.body.addEventListener('submit', function (event) {
var token = $("meta[name='_csrf']").attr("content");
var paramName = $("meta[name='_csrf_parameterName']").attr("content");
$('<input>').attr({
type: 'hidden',
name: paramName,
value: token
}).appendTo(event.target);
}, false);
Use #Kristian Antonsen's answer, or you can use:
$('button').click(function() {
preventDefault();
captureForm();
});

Disable AddEventListener On Submit

I am trying to disable the function I pass to addEventListener when the user clicks on submit. I put code in to prevent user from leaving page if they have entered data on any of the fields. This works fine. If the user tries to navigate away they get a warning as expected. However, I can't seem to figure out how to disable this feature once all of the fields are populated and the user clicks submit. As it stands, they are prompted to make sure they want to navigate away when they click on submit and I don't want this to happen when the user clicks submit.
I've tried something like the below, to try to unbind the beforeunload function based on submit, but this isn't working. I feel like this is the right general idea, but I'm struggling to make this work as I want it to.
$('form').submit(function() {
$(window).unbind('beforeunload');
});
$(window).on('beforeunload',function(){
return '';
});
The code below works as expected:
window.addEventListener('beforeunload', function (event) {
console.log('checking form');
let inputValue = document.querySelector('#myInput').value;
if (inputValue.length > 0) {
console.log(inputValue);
event.returnValue = 'Are you sure you wish to leave?';
}
event.preventDefault();
});
If the user clicks submit I want the beforeunload function to be turned off essentially.
Was able to solve this problem using the suggestion that was made by Bipperty via this SO issue...Narrow Down BeforeUnload To Only Fire If Field Is Changed or Updated. Ultimately the code below is what I used to turn off beforeunload when submitting the form....
var submitting = false;
window.addEventListener("beforeunload", function (event) {
console.log('checking form');
let inputValue = document.querySelector('#myInput').value;
if(inputValue.length > 0 && submitting === false) {
console.log(inputValue);
event.returnValue = 'Are you sure you wish to leave?';
}
event.preventDefault();
});
document.addEventListener("submit", function(event) {
submitting = true;
});
If you bind a handler using .on() you can remove the bound event using .off()
$('form').submit(function() {
$(window).off('beforeunload');
});
$(window).on('beforeunload',function(){
return '';
});
However, I feel in your scenario you don't really need the beforeunload at all if you handle your form submit logically.
I've mocked up an example of how you can logically submit the form if a user chooses to submit the form based on a condition (in this case if all fields aren't filled).
$('form').on('submit', function (e) {
var inputs = $(':text', this);
console.log(inputs.length)
var validInputs = inputs.filter(function () {
return $(this).val().length;
}).length;
if (validInputs > 0 && validInputs < inputs.length) {
var r = confirm("Are you sure you want to leave?");
if (!r) e.preventDefault()
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form action="http://google.com" method="get">
<input name="a" placeholder="Input 1">
<input name="b" placeholder="Input 2">
<input name="c" placeholder="Input 3">
<button type="submit">Submit</button>
</form>
Update
To prompt the user before leaving a form:
window.onbeforeunload = function(){
return 'Are you sure you want to leave?';
};
See this post
Use the required attribute on each field and you won't need to do all of that. The following demo will refuse any attempts to submit it's form if there's a blank field. It will send to a live test server and a response will be displayed verifying a successful submission.
Demo
window.onbeforeunload = function(){
return 'Are you sure you want to leave?';
};
label {
display: inline-block;
width: 75px
}
[type=submit] {
margin-left: 200px
}
<form id='form' action='http://httpbin.org/post' method='post' target='response'>
<label>Name: </label><input name='Name' type='text' required><br>
<label>Cell: </label><input name='Cell' type='tel' required><br>
<label>Date: </label><input name='Date' type='date' required><br>
<input type="submit">
</form>
<iframe src='about:blank' name='response'></iframe>

Javascript not inserting input

I've been trying to use stripe to accept payment and I've been trying to make a rough prototype for it from a guide I found but I can't seem to get it working. The new input named "stripeToken" never inserts after the submit. This causes my PHP script to never execute. I'm trying to understand why it never inserts. Here's the scripts:
Javascript: (In the head of page)
<script src="https://js.stripe.com/v2/"></script>
<script type="text/javascript">
Stripe.setPublishableKey('mykeyishere');
</script>
<script>
// Event Listeners
$('#payment-form').on('submit', generateToken);
var generateToken = function (e) {
var form = $(this);
// No pressing the buy now button more than once
form.find('button').prop('disabled', true);
// Create the token, based on the form object
Stripe.create(form, stripeResponseHandler);
// Prevent the form from submitting
e.preventDefault();
};
</script>
HTML/Javascript: (Tried JS both in the head and in the form)
<form action="index.php" method="POST" id="payment-form">
<script>
var stripeResponseHandler = function (status, response) {
var form = $('#payment-form');
// Any validation errors?
if (response.error) {
// Show the user what they did wrong
form.find('.payment-errors').text(response.error.message);
// Make the submit clickable again
form.find('button').prop('disabled', false);
} else {
// Otherwise, we're good to go! Submit the form.
// Insert the unique token into the form
$('<input>', {
'type': 'hidden',
'name': 'stripeToken',
'value': response.id
}).appendTo(form);
// Call the native submit method on the form
// to keep the submission from being canceled
form.get(0).submit();
}
};</script>
<span class="payment-errors"></span>
<div class="row">
<label>
<span>Card Number</span>
<input type="text" data-stripe="number">
</label>
</div>
<div class="row">
<label>
<span>CVC</span>
<input type="text" data-stripe="cvc">
</label>
</div>
<div class="row">
<label>
<span>Expiration (MM/YYYY)</span>
<input type="text" data-stripe="exp-month">
</label>
<input type="text" data-stripe="exp-year">
</div>
<button type="submit">Submit</button>
</form>
You should remove that script tag from inside the form and put it next to the other script tag.
also try wrapping your event binding in a document.ready
$(document).ready(function(){
$('#payment-form').on('submit', generateToken);
var stripeResponseHandler = function (status, response) {
var form = $('#payment-form');
// Any validation errors?
if (response.error) {
// Show the user what they did wrong
form.find('.payment-errors').text(response.error.message);
// Make the submit clickable again
form.find('button').prop('disabled', false);
} else {
// Otherwise, we're good to go! Submit the form.
// Insert the unique token into the form
$('<input>', {
'type': 'hidden',
'name': 'stripeToken',
'value': response.id
}).appendTo(form);
// Call the native submit method on the form
// to keep the submission from being canceled
form.get(0).submit();
}
};
var generateToken = function (e) {
var form = $(this);
// No pressing the buy now button more than once
form.find('button').prop('disabled', true);
// Create the token, based on the form object
Stripe.create(form, stripeResponseHandler);
// Prevent the form from submitting
e.preventDefault();
};
});
From what I can guess ( and its not a good guess), is that the #payment-form does not get bound correctly because the script is getting ran before the dom is ready?
Also another thing caught my eye. You have e.preventDefault() which stops the form from being submitted, but then you have a responsehandler. does that response handler get called? Is there some request that goes out to stripe and comes back?
Check in your network window and see if that is happening. The form only gets submitted in the form.get(0).submit(); part of the response handler, so after stripe completes.

Form - submit POST request to multiple iframes

I know that it is possible to submit POST request to an iframe by using target attribute.
Is there any way to submit POST request from one form to multiple iframes at the same time?
Both HTML and JS solutions are acceptable.
A Javascript solution would be your best bet.
<form id="form">
<input type="text" name="xyz" value="random data" />
<button type="submit">Go</button>
</form>
In JS, you would attach an event listener to your form when it is submitted. The listener would trigger a function that could send the form data to multiple targets:
var form = document.getElementById("form");
if(form.attachEvent) {
form.attachEvent("submit", submitForm);
} else {
form.addEventListener("submit", submitForm);
}
function submitForm(e) {
if(e.preventDefault) {
e.preventDefault();
}
this.target = "first_iframe";
this.submit();
var secondForm = this.cloneNode();
secondForm.target = "second_iframe";
secondForm.submit();
}

How can I run a script when 1 of my 2 submit buttons within 1 form is clicked?

Hi I have 2 submit buttons within one form. The script below works to help prevent empty fields from being submitted by sending an alert msg to the user. However I only need it to run with one of my two submit buttons is clicked. So in other words if one button a if clicked it would submit the form with or without blank fields, and the other button would run the script below and not allow the form to be submitted with blank fields. Any help is greatly appreciated, Thanks.
<script type="text/javascript">
$('form').on('submit', function () {
var thisForm = $(this);
var thisAlert = thisForm.data('alert');
var canSubmit = true;
thisForm.find('[data-alert]').each(function(i) {
var thisInput = $(this);
if ( !$.trim(thisInput.val()) ) {
thisAlert += '\n' + thisInput.data('alert');
canSubmit = false;
};
});
if( !canSubmit ) {
alert( thisAlert );
return false;
}
});
</script>
Instead of wiring up to the form submit event, wire up to the click event of the button that you want to validate with. Returning true from a click event will allow the submit to occur, and false will block it.
You have one form and two submit buttons which, by default, will both submit the form. To prevent one button from submitting, add a click handler that both prevents the default submit action and does whatever else you want that button to do.
HTML
<form id="form">
<input type="text" value="something" />
<input id="submit1" type="submit" value="send" />
<input id="submit2" type="submit" value="ignore" />
</form>
JavaScript
$('#submit2').on('click', function (event) {
event.preventDefault();
// Form will not be submitted
// Do whatever you need to do when this button is clicked
});
$('form').on('submit', function () {
var thisForm = $(this);
var thisAlert = thisForm.data('alert');
var canSubmit = true;
thisForm.find('[data-alert]').each(function(i) {
var thisInput = $(this);
if ( !$.trim(thisInput.val()) ) {
thisAlert += '\n' + thisInput.data('alert');
canSubmit = false;
};
});
if( !canSubmit ) {
alert( thisAlert );
return false;
}
});
Demo https://jsfiddle.net/BenjaminRay/dqqfLxav/
You may try adding the click event and adding classes to the submit buttons. So you know which button click will submit the form accordingly.
$('form button').click(function(){
if($(this).hasClass('.submit-without-validation')) {
$('form').submit();
}
if($(this).hasClass('.submit-with-validation')) {
//Do your validation and then submit
}
});
There are so many answered that you can use to achieve what you want. And you can try this one also. Here is some explanation. Basically, you need can use html5 data attribute to set the value to differentiate both button. When the button was clicked, you can check the value using condition as following code :
HTML
<form>
<input type="text" value="" id="name"/>
<input type="submit" class="btn_submit" value="Submit validate" data-valid="yes"/>
<input type="submit" class="btn_submit" value="Submit without validate" data-valid="no"/>
</form>
JS
$(document).on('click', '.btn_submit', function(e){
e.preventDefault();
var data_valid = $(this).data('valid');
if(data_valid == "yes")
{
// doing your stuff here for validation like example below
var input = $('#name').val();
if(input=="")
{
alert('required');
return;
}
// After the validation process finish, submit the form
$('form').submit();
}
else
{
// submit without validation
$('form').submit();
}
});

Categories