Is there a generic solution to determining which input (e.g., text, submit button, etc.) was used to submit a form using jQuery or plain Javascript?
I'm well aware that you can bind to click events on submit buttons:
$('[type=submit]').on('click', function(event) {
event.preventDefault();
var $submit = $(this);
$submit.closest('form').trigger('submit', [$submit]);
});
I'm also aware that you can listen for the Enter key on text inputs:
$('input').on('keypress', function(event) {
if (event.which == 13) {
event.preventDefault();
var $input = $(this);
$input.closest('form').trigger('submit', [$input]);
}
});
Where the form listens for the submit event:
$('#the_form').on('submit', function(event, $submit) {
// ...
});
But is there a more generic solution without the need for special logic for submit buttons and text inputs (and any future type of input)?
Have you considered seeing what element has the focus on submit?
$(document).ready(function() {
var target = null;
$('#the_form :input').focus(function() {
target = this;
alert(target);
});
$('#the_form').submit(function() {
alert(target);
});
});
Related
I am using following code to tab through form elements using enter key. Problem is that this code skip select2 elements.
$('body').on('keydown', 'input, select', function(e) {
if (e.key === "Enter") {
var self = $(this), form = self.parents('form:eq(0)'), focusable, next;
focusable = form.find('input,a,select,button,textarea').filter(':not([disabled]):not([tabindex="-1"]):visible');
next = focusable.eq(focusable.index(this)+1);
if (next.length) {
next.focus();
} else {
//form.submit();
}
return false;
}
});
Change your keydown to keyup
$('body').on('keyup', 'input, select', function(e)
Reason is keydown is already handled in select2 library for choosing an item
I've just looked at the form validation section in Bootstrap 4.4 (https://getbootstrap.com/docs/4.4/components/forms/#how-it-works) and have implemented the code into my project, the code example and script implementation to trigger the validation looks great!
I was wondering whether it's possible to implement this validation as the user is filling out the form rather than when trying to submit the form?
For instance, if I have two inputs, First Name & Last Name, both of which are required, when I change to the Last Name field, can I get the validation check to trigger for the field I've just filled out?
E.g, validation on the fly?
My current validation (triggered when clicking the form submit button) is:
function validateForm () {
var forms = document.getElementsByClassName('needs-validation')
var validation = Array.prototype.filter.call(forms, function(form) {
console.log(form.checkValidity())
if (form.checkValidity() === false) {
event.preventDefault()
event.stopPropagation()
// get the "first" invalid field
var errorElements = document.querySelectorAll('.form-control:invalid')
// scroll the user to the invalid field
window.scrollTo(0, getOffset(errorElements[0]).top)
}
form.classList.add('was-validated')
})
}
The checkValidity() function works on individual inputs too. Bind the blur handler to each input, and then add class is-valid/is-invalid to each input after validation...
(function() {
'use strict';
window.addEventListener('load', function() {
// Fetch all the forms we want to apply custom validation styles
var inputs = document.getElementsByClassName('form-control')
// Loop over each input and watch blue event
var validation = Array.prototype.filter.call(inputs, function(input) {
input.addEventListener('blur', function(event) {
// reset
input.classList.remove('is-invalid')
input.classList.remove('is-valid')
if (input.checkValidity() === false) {
input.classList.add('is-invalid')
}
else {
input.classList.add('is-valid')
}
}, false);
});
}, false);
})()
https://codeply.com/p/mzBNbAlOvQ
You can add a blur event listener to the inputs, that call your function once triggered.
const inputs = document.querySelectorAll("#form input");
inputs.forEach(e => e.addEventListener("blur", validateForm));
<form id="form">
<input type="text" placeholder="text input">
<input type="text" placeholder="text input">
</form>
#Ryan H To the #Zim code; added or brought back bootstrap's default code (while allowing real-time validation) to not let form submission happen if there are invalid fields on submission. The full code looks like below.
// Example starter JavaScript for disabling form submissions if there are invalid fields
(function() {
'use strict';
window.addEventListener('load', function() {
// Fetch all the forms we want to apply custom Bootstrap validation styles to
var forms = document.getElementsByClassName('needs-validation');
// Loop over them and prevent submission
var form_Validation = Array.prototype.filter.call(forms, function(form) {
form.addEventListener('submit', function(event) {
if (form.checkValidity() === false) {
event.preventDefault();
event.stopPropagation();
}else{event.preventDefault(); processForm();}
form.classList.add('was-validated');
}, false);
});
//Below code to check every input field
var inputs = document.getElementsByClassName('form-control');
var input_Validation = Array.prototype.filter.call(inputs, function(input){
input.addEventListener('blur', function(event){
input.classList.remove('is-invalid')
input.classList.remove('is-valid')
if (input.checkValidity() === false) {
input.classList.add('is-invalid')
}else{input.classList.add('is-valid')}
// form.classList.add('was-validated');
}, false);
});
//End of block that checks each input field
}, false); //window load event listener container
})();// Immediately invoked function container end
I have a WordPress site and there is Contact form 7 plugin and I want to add attr to submit button to disable double submission.
Now I have this code to prevent double submission
$(document).on('click', '.wpcf7-submit', function(e){
if( $('.ajax-loader').hasClass('is-active') ) {
e.preventDefault();
return false;
}
});
but I want to add attr disabled while form sending or getting error response for better user experience
Improving on Matt's answer -
$('.wpcf7-form').on('submit', function() {
$(this).find('.wpcf7-submit').attr('disabled', true);
});
This would disable the submit button when clicked on it. Now to get that activated again after success or failure you would need to remove the attribute after the submission is complete(whether success or failure). Since the plugin developer is a bit whimsical about how the events work, I am writing this solution for first quarter of 2019 -
$('.wpcf7').on('wpcf7submit', function (e) {
$(this).find('.wpcf7-submit').removeAttr('disabled');
});
where '.wpcf7' is the parent container of the form, '.wpcf7-form' is the form itself. The 'wpcf7submit' is event listener that the DOM listens to, after the form gets submitted(irrespective of the fact that is valid or invalid).
This will disable the button and submit the form. You need to re-call submit after disabling the button.
jQuery( '.wpcf7-submit' ).click(function() {
jQuery( this ).attr( 'disabled', true );
jQuery( this ).submit();
});
This will re-enable the button if there's an error with the submission.
document.addEventListener( 'wpcf7invalid', function() {
jQuery( '.wpcf7-submit' ).attr( 'disabled', false );
}, false );
$(document).on('click', '.wpcf7-submit', function(e){
$(this).prop('disabled',true);
});
I implemented this script to help prevent multiple submissions. The biggest difference from the others is that it works with multiple CF7 forms on each page. Basically, it disables the form and the submit button on submit (since a form can also be submitted with an Enter-press), adds a new label "Please Wait.." to the submit button, and re-enables them if there are input errors. Also, not dependent on jQuery (Vanilla JS).
(function () {
var elems = document.querySelectorAll('.wpcf7');
if (!elems.length) {
return false;
}
var forms = document.querySelectorAll('.wpcf7-form');
if (!forms.length) {
return false;
}
function _evtFormSubmit() {
this.disabled = true;
var submitBtn = this.querySelector('button[type="submit"]');
submitBtn.disabled = true;
submitBtn.setAttribute('data-default-text', submitBtn.innerText);
submitBtn.innerHTML = '<span>Please wait...</span>';
}
function _evtInvalid(e) {
var thisForm = document.querySelector('#' + e.detail.id + ' form');
thisForm.disabled = false;
var submitBtn = thisForm.querySelector('button[type="submit"]');
setTimeout(function() {
submitBtn.disabled = false;
submitBtn.innerHTML = '<span>' + submitBtn.getAttribute('data-default-text') + '</span>';
}, 600); // give it a bit of time in case it is a fast submit
}
for(var i = forms.length-1; i >= 0; i--) {
forms[i].addEventListener('submit', _evtFormSubmit, false);
}
for(i = elems.length-1; i >= 0; i--) {
elems[i].addEventListener('wpcf7invalid', _evtInvalid, false);
}
})();
Note: if you have more than one submit button (why?), this only affects the first button in the form.
For future people who are looking for a solution here. Simple SCSS/CSS option without Javascript need. For me is work pefect. It always works reliably for me. (2022)
.wpcf7-form {
&.submitting {
.wpcf7-submit {
pointer-events: none;
}
}
}
We're trying to make a generic approach for a piece of software we are developing that ties into form fields.
So far so good but we're running in to an edge case that prevents submitting a form/field that has another handler tied in to it.
Here's the (condensed) use case:
HTML:
<form id="form1">
<input type=field id="field1"/>
</form>
click to submit
Normal behaviour is that when a user types 'foo' into the field and hits enter, the form is handled and submitted to the correct 'endpoint' which isn't necessarily the defined one in the form's opening tag. There could be some function (from somewhere else) that handles this enter-event.
Unfortunately, we can't predict what that function is, we like to keep it generic.
In the above HTML, clicking on the link should trigger an enter-event on the form field that mimics the browser/user behaviour and thus some unknown handler.
This is our Javscript (we're using jquery):
$('#field1').keypress(function (event) {
if (event.which == 13) {
console.log("enter pressed");
//return false; only if needed
}
});
$( "#link" ).click(function() {
var e = jQuery.Event('keypress');
e.which = 13; // #13 = Enter key
$("#field1").focus();
$("#field1").trigger(e);
})
When entering 'foo' in the field and pressing enter the form gets submitted. But when we click the link we do a focus() and then firing the key-event but the form isn't submitted.
We can't use a submit() because of the unknown handlers.
Try the code here: http://codepen.io/conversify/pen/yOjQob
What happens when enter key is pressed is, if the input is inside a form, the form is submitted. This is the default behavior. When you simulate a key press, you should do the same, unless the default behavior is prevented.
$('#field1').keypress(function (event) {
if (event.which == 13) {
console.log("enter pressed");
// event.preventDefault(); if needed
}
});
$( "#link" ).click(function() {
var e = jQuery.Event('keypress');
e.which = 13; // #13 = Enter key
$("#field1").focus();
$("#field1").trigger(e);
var form=$("#field1").closest("form");
if(form&&!e.isDefaultPrevented()) form.submit();
})
Now you can pass your event object to the handlers and they can prevent the submit if they want so, or you can prevent it in your keypress handler.
You should separate out the form handler from the enter and click handlers.
var formHandler = function(e) {
// ... code to submit form ...
console.log("form handled");
};
Then set your keypress handler like this:
$('#field1').keypress(function (event) {
if (event.which == 13) {
formHandler();
}
});
And your click handler like this:
$( "#link" ).click(function() {
formHandler();
});
You can unbind the unknown handlers using unbind('submit') and then use submit() like following.
$("#link").click(function () {
$("#form1").unbind('submit').submit();
});
I am handling the content inside a textarea using binding a function to the event "input propertychange"
Like this:
$('#textarea').bind('input propertychange', function () {
var textarea = document.getElementById('textarea');
window.lastLineWriting = textarea.value.substr(0, textarea.value.length).split("\n").length;
var writingOnLine = textarea.value.substr(0, textarea.selectionStart).split("\n").length;
if (writingOnLine < window.lastLineWriting) {
//dont write on textarea
}
});
I don't know how to prevent the char typed by the user's keyboard to appear on the textarea... Inside that if I want to prevent the text to be inserted on textarea..
How can I do this?
you could easily stop the user from typing with this code, using jQuery:
$('textarea').bind('keypress', function (e) {
e.preventDefault();
return false;
});
NOTE:
this code will prevent the user from typing in all the textareas, to bind it specifically to one or some selected elements, you must change the selector to the desired elements.
var editable = false // Your Condition
if(editable != "true"){
$("#textarea" ).attr("disabled",true);
}