JavaScript & HTML Forms: Which button is the submitter? - javascript

I am writing a JavaScript function to pre-process form data. One thing I need to know is which of a number of submit buttons was used.
Roughly, the script has the following outline.
var form=document.querySelector('form#test');
form.onsubmit=processForm;
function processForm() {
// how did I get here
}
<form id="test">
<!-- usual stuff -->
<button type="submit" name="check">Check</button>
<button type="submit" name="doit">Do Stuff</button>
</form>
I know that I could attach the function to the individual submit buttons, but it would be more resilient if I attached it to the form itself.
Is there a form property or some other method for checking which submit button was used?
Thanks

You can attach click handler to each <button> element, create a variable to store clicked button name property, or reference to element, access property or element at submit event
function processForm(e) {
e.preventDefault();
console.log(curr) // `curr`: `name` of clicked `button"` element
}
var submit = document.querySelectorAll("button[type=submit]");
var curr;
for (var i = 0; i < submit.length; i++) {
submit[i].onclick = function(e) {
curr = e.target.name; // store reference to `name`, or element
}
}

Usually the clicked submit button is sent as it is considered active.
I believe that when there is only 1 submit button the form will submit on enter but when multiple it will only submit on click.
Thus in your backend, you can just check for the existence of either form button to know which button was used.
Relevant section of HTML rfc:
https://www.w3.org/TR/html401/interact/forms.html#h-17.13.2
However I wasn't able to find a good browser compatibility for this so your mileage may vary.

I believe the answer to my question is that you can’t. Once the submit event is activated, it doesn’t seem to know or care how it got there.
The only solution, as mentioned in my original question, is to attach a listener to the submit button[s].
Here is a stub of the processing code:
window.onload=init;
function init() {
var form=document.querySelector('form#test');
var submitButtons=form.querySelectorAll('button:not([type]),button[type="submit"],input[type="submit"]');
if(submitButtons.length) {
for(var i=0;i<submitButtons.length;i++) submitButtons[i].addEventListener('click',process);
}
function process(e) {
var submitter=this;
var form=this.form;
// etc
}
}
Oh well …

Related

Submitting POST Request only once [duplicate]

I have a submit button at the end of the form.
I have added the following condition to the submit button:
onClick="this.disabled=true;
this.value='Sending…';
this.form.submit();"
But when it moves to the next page, the parameters did not pass and null values are passed.
You should first submit your form and then change the value of your submit:
onClick="this.form.submit(); this.disabled=true; this.value='Sending…'; "
Probably you're submitting the form twice.
Remove the this.form.submit() or add return false at the end.
you should end up with onClick="this.disabled=true; this.value='Sending…';"
tested on IE11, FF53, GC58 :
onclick="var e=this;setTimeout(function(){e.disabled=true;},0);return true;"
You need to disable the button in the onsubmit event of the <form>:
<form action='/' method='POST' onsubmit='disableButton()'>
<input name='txt' type='text' required />
<button id='btn' type='submit'>Post</button>
</form>
<script>
function disableButton() {
var btn = document.getElementById('btn');
btn.disabled = true;
btn.innerText = 'Posting...'
}
</script>
Note: this way if you have a form element which has the required attribute will work.
Disabled HTML forms elements aren't sent along with the post/get values when you submit the form. So if you disable your submit button once clicked and that this submit button have the name attribute set, It will not be sent in the post/get values since the element is now disabled. This is normal behavior.
One of the way to overcome this problem is using hidden form elements.
the trick is to delayed the button to be disabled, and submit the form you can use
window.setTimeout('this.disabled=true',0);
yes even with 0 MS is working
Using JQuery, you can do this..
$("#submitbutton").click(
function() {
alert("Sending...");
window.location.replace("path to url");
}
);
If you disable the button, then its name=value pair will indeed not be sent as parameter. But the remnant of the parameters should be sent (as long as their respective input elements and the parent form are not disabled). Likely you're testing the button only or the other input fields or even the form are disabled?
Here's a drop-in example that expands on Andreas Köberle's solution. It uses jQuery for the event handler and the document ready event, but those could be switched to plain JS:
(function(document, $) {
$(function() {
$(document).on('click', '[disable-on-click], .disable-on-click', function() {
var disableText = this.getAttribute("data-disable-text") || 'Processing...';
if(this.form) {
this.form.submit();
}
this.disabled = true;
if(this.tagName === 'BUTTON') {
this.innerHTML = disableText;
} else if(this.tagName === 'INPUT') {
this.value = disableText;
}
});
});
})(document, jQuery);
It can then be used in HTML like this:
<button disable-on-click data-disable-text="Saving...">Click Me</button>
<button class="disable-on-click">Click Me</button>
<input type="submit" disable-on-click value="Click Me" />
I don't think you need this.form.submit(). The disabling code should run, then it will pass on the click which will click the form.
Another solution i´ve used is to move the button instead of disabling it. In that case you don´t have those "disable" problems.
Finally what you really want is people not to press twice, if the button is not there they can´t do it.
You may also replace it with another button.
function xxxx() {
// submit or validate here , disable after that using below
document.getElementById('buttonId').disabled = 'disabled';
document.getElementById('buttonId').disabled = '';
}
Your question is confusing and you really should post some code, but this should work:
onClick="this.disabled=true; this.value='Sending...'; submitForm(); return false;"
I think that when you use this.form.submit() it's doing what happens naturally when you click the submit button. If you want same-page submit, you should look into using AJAX in the submitForm() method (above).
Also, returning false at the end of the onClick attribute value suppresses the default event from firing (in this case submitting the form).
A better trick, so you don't lose the value of the button is
function showwait() {
document.getElementById('WAIT').style['display']='inline';
document.getElementById('BUTTONS').style['display']='none';
}
wrap code to show in a div
id=WAIT style="display:none"> text to display (end div)
wrap code to hide in a div
id=BUTTONS style="display:inline"> ... buttons or whatever to hide with
onclick="showwait();"
(end div)
In my case this was needed.
Disable submit button on form submit
It works fine in Internet Explorer and Firefox without it, but it did not work in Google Chrome.
The problem is that you are disabling the button before it can actually trigger the submit event.
I think easy way to disable button is :data => { disable_with: "Saving.." }
This will submit a form and then make a button disable, Also it won't disable button if you have any validations like required = 'required'.
In this working example, the user confirms in JavaScript that he really wants to abort. If true, the button is disabled to prevent double click and then the code behind which updates the database will run.
<asp:button id="btnAbort" runat="server" OnClick="btnAbort_Click" OnClientClick="if (!abort()) {return false;};" UseSubmitBehavior="false" text="Abort" ></asp:button>
I had issues because .net can change the name of the button
function abort() {
if (confirm('<asp:Literal runat="server" Text="Do you want to abort?" />')) {
var btn = document.getElementById('btnAbort');
btn.disabled = true;
btn.innerText = 'Aborting...'
return true;
}
else {
return false;
}
}
Because you are overriding the OnClick with OnClientClick, even if your validation method succeeds, the code behind wont work. That's why you set UseSubmitBehavior to false to make it work
PS: You don't need the OnClick if your code is in vb.net!
Okay, i did a lot of research on how to make this work perfectly.
So the best option is to create a set timeout for disabling a button onclick.
Now, the problem arise when there is a submit function running on the backend. Then the events become stacked in a queue and whenever the javascript "button.disabled == true"is added to the onclick event, only the first action(i.e. disabling the button) gets triggered and not the submit action which is running in the backend(This backend submit function can comprise of anything such as $.ajax).
For disabling Single button on click :
function() { //i always create annonymous function to avoid polluting global
space
var btn = document.getElementsByClassName("btn");
btn.onclick = function() {
setTimeout(function() {
backButton.disabled = true;
}, 0);
};
}
}();
This code will disable your button and also would run the function on the queue. timeout = 0 actually is used for firing subsequent backend tasks.
For disabling all btns in the screen :
(function() {
let i, element, list, o;
element = document.getElementsByClassName("classx");
if (element) {
element = element[0];
list = element.getElementsByTagName("button");
for (i = 0; i < list.length; i++) {
o = list[i];
o.onclick = function() {
setTimeout(function() {
let i;
for (i = 0; i < list.length; i++) {
list[i].disabled = true;
}
}, 0);
return true;
}
}
}
})();
This would help you disable all of the buttons present in the page. (Just use it according to your usecase.)
Also, this(disabled button) is a good use case for settimeout=0, functionality description as it will "defer" the call until the currently "stacked javascript events" are finished.
Thank you and hope this helps someone's in the future.
I did the trick. When set timeout, it works perfectly and sending all values.
$(document).ready(function () {
document.getElementById('btnSendMail').onclick = function () {
setTimeout(function () {
document.getElementById('btnSendMail').value = 'Sending…';
document.getElementById('btnSendMail').disabled = true;
}, 850);
}
});

Having issues with setting an even listener to prevent default in input field with javascript

I am trying to make a simple password generator and i want the password generation to happen on the click of a button and that part works when i test it in the console. And now to implement it on sort of a real web page, the password generated to the input field doesn't stay!!, i know to use the .preventDefault() method but i don't know hot to apply it in this case using an event listener for when the value of the input field changes.
I couldn't add the html because it looks strange when i add it, but it looks like this:
Password: <input type="text" name="password" id="password" value="">
<button id="button" onclick="makePassword()">Get password</button>
here is my code below:
var capitalAlphabets=["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"];
var smallAlphabets=["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"];
var numbers=[1,2,3,4,5,6,7,8,9,0,];
function randomCapital(){
var capital=capitalAlphabets[Math.floor(Math.random()*capitalAlphabets.length)];
return capital;
}
function randomSmall(){
var small=smallAlphabets[Math.floor(Math.random()*smallAlphabets.length)];
return small;
}
function randomNumber(){
var number=numbers[Math.floor(Math.random()*numbers.length)];
return number;
}
var password="";
function makePassword(){
password="";
for(var i=0; i<=12; i++){
password=password+randomCapital()+randomSmall()+randomNumber();
// console.log(i + password);
}
console.log(password);
input=document.getElementById("password");
input.value=password;
}
//having issues with setting an even listener to prevent default in input field
You probably have your button inside a form so it is interpreted as a submit button (<button type="submit">). Pressing enter inside an input field inside a form will click on the first submit button inside the form. Just explicity make the button type a button so clicking it will not submit the form and refresh the page:
<button type="button" onclick="makePassword()">Get password</button>
If you want to add an event listener, use document.getElementById to get the DOM element to add a keypress event listener to and if the event's keycode is 13 (enter), prevent the default action.
document.getElementById("password").addEventListener("keypress", function(e){
if(e.keyCode==13){
e.preventDefault();
}
});
Overall, using onclick="" for a button is bad practice.
You should add an eventListener for your button instead:
var button = document.getElementById("button");
button.addEventListener("click", function(event) {
event.preventDefault();
makePassword();
});
That should work much better, let me know if you have any questions.
http://jsfiddle.net/316xjkqu/2/

Specifying button clicked in multiple forms in javascript

I need help with some Javascript.
Inside my html I have a form that repeated twice.
<form method='post' action='php page'>
<input type=text id=something name=something value='' />
<input type="submit" id="final_submit" value="yes">
</form>
This exact form is repeated twice. In javascript when someone clicks on the submit button I need to be able to determine which button was clicked to get the value of something in that form. Right now its automatically just getting the value for the first form even though I click the button on the second form.
Any ideas please.
As mention in the comments, using duplicate id is wrong. Here is a way to get the value of the input that will work also in using older browsers document.forms and forms.element
var forms = document.forms;
for(var i=0, l= forms.length; i++){
forms[i].addEventListener('submit', function(e){
e.preventDefault();
var form = e.target;
var value = form.elements[0].value;
})
}
This will add a submit event listener to every form in your side and that stops the event and get the value from the first input field in this form.
Is that what you need?
function determineForm(e)
{
// This prevents the form from actually being submitted.
// Just remove it when you are done debugging.
e.preventDefault();
if (document.querySelectorAll("form")[0] === e.target)
{
alert("Form1");
}
else
{
alert("Form2");
}
}
document.addEventListener("submit", determineForm, false);

Adding hidden field in beforeunload

On my page I'm using a form which on submit should get some extra hidden fields. The problem however is that I can't know the name/id of the form nor the submit button so I can't use functions like onClick etc. Therefore I'm using the beforeunload event to trigger an event when the user tries to leave the page (this includes submitting a form). I'm using the document.activeElement to find out what triggered the event and if it's a form/submit I'm adding the hidden fields to the form.
Stripping down the code it comes down to something like this:
var javascriptData = ['val1','val2','val3']; // usually gets values dynamically and can differ in size
$(window).bind('beforeunload', function(e) {
var activeForm = document.activeElement.form;
for(var i = 0; i < javascriptData.length; i++){
$(activeForm).append('<input type="hidden" name="test-data[]" value="'+javascriptData[i]+'" />');
}
return false; // just for debug purposes.
}
The code works and the element is added to the form but it doesn't show up in the $_POST on the next page. However, the final line of code (return false) creates a pop-up asking if I want to leave the page, if I stay on the page, press the submit button again and then leave the page and check $_POST, the field there. My guess is that the data for the $_POST is collected before the beforeunload function is triggered.
My question is: "Is there a way around this so I can add a hidden field to a form in the beforeunload event?".
Help is much appreciated, thanks in advance.
Why not add it to all forms on the page?
$(document).ready(function() {
$("form").append('<input type="hidden" name="test-data[]" value="test" />');
});
Like the comments above mentioned, you can just hook onto the submit event.
$('form').submit(function() {
for(var i = 0; i < javascriptData.length; i++){
$(this).append('<input type="hidden" name="test-data[]" value="'+javascriptData[i]+'" />');
}
}

How to disable submit button once it has been clicked?

I have a submit button at the end of the form.
I have added the following condition to the submit button:
onClick="this.disabled=true;
this.value='Sending…';
this.form.submit();"
But when it moves to the next page, the parameters did not pass and null values are passed.
You should first submit your form and then change the value of your submit:
onClick="this.form.submit(); this.disabled=true; this.value='Sending…'; "
Probably you're submitting the form twice.
Remove the this.form.submit() or add return false at the end.
you should end up with onClick="this.disabled=true; this.value='Sending…';"
tested on IE11, FF53, GC58 :
onclick="var e=this;setTimeout(function(){e.disabled=true;},0);return true;"
You need to disable the button in the onsubmit event of the <form>:
<form action='/' method='POST' onsubmit='disableButton()'>
<input name='txt' type='text' required />
<button id='btn' type='submit'>Post</button>
</form>
<script>
function disableButton() {
var btn = document.getElementById('btn');
btn.disabled = true;
btn.innerText = 'Posting...'
}
</script>
Note: this way if you have a form element which has the required attribute will work.
Disabled HTML forms elements aren't sent along with the post/get values when you submit the form. So if you disable your submit button once clicked and that this submit button have the name attribute set, It will not be sent in the post/get values since the element is now disabled. This is normal behavior.
One of the way to overcome this problem is using hidden form elements.
the trick is to delayed the button to be disabled, and submit the form you can use
window.setTimeout('this.disabled=true',0);
yes even with 0 MS is working
Using JQuery, you can do this..
$("#submitbutton").click(
function() {
alert("Sending...");
window.location.replace("path to url");
}
);
If you disable the button, then its name=value pair will indeed not be sent as parameter. But the remnant of the parameters should be sent (as long as their respective input elements and the parent form are not disabled). Likely you're testing the button only or the other input fields or even the form are disabled?
Here's a drop-in example that expands on Andreas Köberle's solution. It uses jQuery for the event handler and the document ready event, but those could be switched to plain JS:
(function(document, $) {
$(function() {
$(document).on('click', '[disable-on-click], .disable-on-click', function() {
var disableText = this.getAttribute("data-disable-text") || 'Processing...';
if(this.form) {
this.form.submit();
}
this.disabled = true;
if(this.tagName === 'BUTTON') {
this.innerHTML = disableText;
} else if(this.tagName === 'INPUT') {
this.value = disableText;
}
});
});
})(document, jQuery);
It can then be used in HTML like this:
<button disable-on-click data-disable-text="Saving...">Click Me</button>
<button class="disable-on-click">Click Me</button>
<input type="submit" disable-on-click value="Click Me" />
I don't think you need this.form.submit(). The disabling code should run, then it will pass on the click which will click the form.
Another solution i´ve used is to move the button instead of disabling it. In that case you don´t have those "disable" problems.
Finally what you really want is people not to press twice, if the button is not there they can´t do it.
You may also replace it with another button.
function xxxx() {
// submit or validate here , disable after that using below
document.getElementById('buttonId').disabled = 'disabled';
document.getElementById('buttonId').disabled = '';
}
Your question is confusing and you really should post some code, but this should work:
onClick="this.disabled=true; this.value='Sending...'; submitForm(); return false;"
I think that when you use this.form.submit() it's doing what happens naturally when you click the submit button. If you want same-page submit, you should look into using AJAX in the submitForm() method (above).
Also, returning false at the end of the onClick attribute value suppresses the default event from firing (in this case submitting the form).
A better trick, so you don't lose the value of the button is
function showwait() {
document.getElementById('WAIT').style['display']='inline';
document.getElementById('BUTTONS').style['display']='none';
}
wrap code to show in a div
id=WAIT style="display:none"> text to display (end div)
wrap code to hide in a div
id=BUTTONS style="display:inline"> ... buttons or whatever to hide with
onclick="showwait();"
(end div)
In my case this was needed.
Disable submit button on form submit
It works fine in Internet Explorer and Firefox without it, but it did not work in Google Chrome.
The problem is that you are disabling the button before it can actually trigger the submit event.
I think easy way to disable button is :data => { disable_with: "Saving.." }
This will submit a form and then make a button disable, Also it won't disable button if you have any validations like required = 'required'.
In this working example, the user confirms in JavaScript that he really wants to abort. If true, the button is disabled to prevent double click and then the code behind which updates the database will run.
<asp:button id="btnAbort" runat="server" OnClick="btnAbort_Click" OnClientClick="if (!abort()) {return false;};" UseSubmitBehavior="false" text="Abort" ></asp:button>
I had issues because .net can change the name of the button
function abort() {
if (confirm('<asp:Literal runat="server" Text="Do you want to abort?" />')) {
var btn = document.getElementById('btnAbort');
btn.disabled = true;
btn.innerText = 'Aborting...'
return true;
}
else {
return false;
}
}
Because you are overriding the OnClick with OnClientClick, even if your validation method succeeds, the code behind wont work. That's why you set UseSubmitBehavior to false to make it work
PS: You don't need the OnClick if your code is in vb.net!
Okay, i did a lot of research on how to make this work perfectly.
So the best option is to create a set timeout for disabling a button onclick.
Now, the problem arise when there is a submit function running on the backend. Then the events become stacked in a queue and whenever the javascript "button.disabled == true"is added to the onclick event, only the first action(i.e. disabling the button) gets triggered and not the submit action which is running in the backend(This backend submit function can comprise of anything such as $.ajax).
For disabling Single button on click :
function() { //i always create annonymous function to avoid polluting global
space
var btn = document.getElementsByClassName("btn");
btn.onclick = function() {
setTimeout(function() {
backButton.disabled = true;
}, 0);
};
}
}();
This code will disable your button and also would run the function on the queue. timeout = 0 actually is used for firing subsequent backend tasks.
For disabling all btns in the screen :
(function() {
let i, element, list, o;
element = document.getElementsByClassName("classx");
if (element) {
element = element[0];
list = element.getElementsByTagName("button");
for (i = 0; i < list.length; i++) {
o = list[i];
o.onclick = function() {
setTimeout(function() {
let i;
for (i = 0; i < list.length; i++) {
list[i].disabled = true;
}
}, 0);
return true;
}
}
}
})();
This would help you disable all of the buttons present in the page. (Just use it according to your usecase.)
Also, this(disabled button) is a good use case for settimeout=0, functionality description as it will "defer" the call until the currently "stacked javascript events" are finished.
Thank you and hope this helps someone's in the future.
I did the trick. When set timeout, it works perfectly and sending all values.
$(document).ready(function () {
document.getElementById('btnSendMail').onclick = function () {
setTimeout(function () {
document.getElementById('btnSendMail').value = 'Sending…';
document.getElementById('btnSendMail').disabled = true;
}, 850);
}
});

Categories