I am using the jQuery validation plugin and am trying to adapt the function focusInvalid to my needs. On submit (with invalid fields) I want to:
- Scroll to the first invalid element of the form
- Focus on this element
The validation has to behave almost the same on an iPad/iPhone/... as on a Desktop, which is not trivial as one can only focus an element in iOS based on a user trigger. But that's a different story - see iPad HTML focus for more details.
My first approach was to modify jquery.validate.js directly in order to test my adaptations. This is what I came up with:
focusInvalid: function() {
if ( this.settings.focusInvalid ) {
try {
var firstInvalidElement = $(this.errorList[0].element);
$('html,body').scrollTop(firstInvalidElement.offset().top);
firstInvalidElement.focus()
} catch ( e ) {
// ignore IE throwing errors when focusing hidden elements
}
}
}
Works as expected.
Now I would love to override the default behavior of focusInvalid externally (as in: not modify the original jQuery validation source code).
Here is what I tried so far:
- overriding a function within the jquery validation plugin
- How to focus invalid fields with jQuery validate? (2nd answer)
So, for example:
invalidHandler: function(form, validator) {
var errors = validator.numberOfInvalids();
if (errors) {
var firstInvalidElement = $(validator.errorList[0].element);
$('html,body').scrollTop(firstInvalidElement.offset().top);
firstInvalidElement.focus();
}
}
Unfortunately I am now able to submit the form (even though there are still invalid fields) if I press the ENTER key instead of using the submit button. If I remove this custom invalidHandler, the validation does not have this behaviour.
Any ideas where this change in behaviour comes from?
Edit:
I have created a JSFiddle to demonstrate the issue. In order to reproduce:
- Enter a valid email address
- Press ENTER key
Edit:
Here are the code snippets as pasted in the JSFiddle.
HTML:
<div class="pre-login">
<form action="login" method="post" id="login">
<div class="form-group">
<input type="email" class="form-control" name="email" id="email" placeholder="Email Address" autofocus="autofocus" required />
</div>
<div class="form-group">
<input type="password" class="form-control" name="pass" id="pass" placeholder="Password" required />
</div>
<button type="submit" class="btn btn-success btn-block">Submit</button>
</form>
</div>
JavaScript:
$(function () {
$.validator.setDefaults({
highlight: function (element) {
$(element).closest('.form-group').addClass('has-error');
},
unhighlight: function (element) {
$(element).closest('.form-group').removeClass('has-error');
},
errorElement: 'span',
errorClass: 'error-message',
errorPlacement: function (error, element) {
if (element.parent('.input-group').length) {
error.insertAfter(element.parent());
} else {
error.insertAfter(element);
}
}
});
$('#login').validate({
invalidHandler: function(form, validator) {
var errors = validator.numberOfInvalids();
if (errors) {
var firstInvalidElement = $(validator.errorList[0].element);
$('html,body').scrollTop(firstInvalidElement.offset().top);
firstInvalidElement.focus();
}
},
rules: {
email: {
required: true,
email: true
},
pass: {
required: true
}
}
});
});