-
-
Save nuxodin/73a2c2423cbbf6818c28ad803985d5c7 to your computer and use it in GitHub Desktop.
/* Copyright (c) 2016 Tobias Buschor https://goo.gl/gl0mbf | MIT License https://goo.gl/HgajeK */ | |
if (!HTMLFormElement.prototype.reportValidity) { | |
HTMLFormElement.prototype.reportValidity = function() { | |
if (this.checkValidity()) return true; | |
var btn = document.createElement('button'); | |
this.appendChild(btn); | |
btn.click(); | |
this.removeChild(btn); | |
return false; | |
}; | |
} | |
if (!HTMLInputElement.prototype.reportValidity) { | |
HTMLInputElement.prototype.reportValidity = function(){ | |
if (this.checkValidity()) return true | |
var tmpForm; | |
if (!this.form) { | |
tmpForm = document.createElement('form'); | |
tmpForm.style.display = 'inline'; | |
this.before(tmpForm); | |
tmpForm.append(this); | |
} | |
var siblings = Array.from(this.form.elements).filter(function(input){ | |
return input !== this && !!input.checkValidity && !input.disabled; | |
},this); | |
siblings.forEach(function(input){ | |
input.disabled = true; | |
}); | |
this.form.reportValidity(); | |
siblings.forEach(function(input){ | |
input.disabled = false; | |
}); | |
if (tmpForm) { | |
tmpForm.before(this); | |
tmpForm.remove(); | |
} | |
this.focus(); | |
this.selectionStart = 0; | |
return false; | |
}; | |
} |
Hmm, I guess you're right, I don't remember what thoughts I had.
No sorry, you are wrong, this.submit() will submit the form, regardless of validity.
@nuxodin hmm, yeah, I just tried it again and it submits. Something must have been wrong with whatever I tried yesterday.
I needed a way to reportValidity
on a specific input instead of just the form. Thought I would share:
function reportValidity(input) {
if (input.checkValidity()) {
return true
}
if (input.reportValidity) {
input.reportValidity()
} else if (input.form) {
const form = input.form
const siblings = Array.from(form.elements).filter(
e => e !== input && !!e.checkValidity && !e.disabled
)
for (const sibling of siblings) {
sibling.disabled = true
}
const button = document.createElement("button")
form.appendChild(button)
button.click()
form.removeChild(button)
for (const sibling of siblings) {
sibling.disabled = false
}
} else {
input.focus()
}
return false
}
It's based on the same concept, but takes advantage of the fact that the html5 form validation api ignores disabled inputs.
@lukescott
Great Work!
I updated my gist with a similiar polyfill.
- handles Inputs without a form
- extended Native HTMLInputElement
- reused the form.reportValidity-polyfill
- no es6 for ie11
- but it needs some polyfills for ie11 (Array.from, Element-Methods: before, after and remove)
- tested in ie11 but not in old safaris
@nuxodin I think there is a bug. It looks like you still use this.form
when it could be undefined. You probably want this:
if (!HTMLInputElement.prototype.reportValidity) {
HTMLInputElement.prototype.reportValidity = function(){
if (this.checkValidity()) return true
var form = this.form;
var tmpForm;
if (!form) {
tmpForm = document.createElement('form');
tmpForm.style.display = 'inline';
this.before(tmpForm);
tmpForm.append(this);
}
var siblings = Array.from(form.elements).filter(function(input){
return input !== this && !!input.checkValidity && !input.disabled;
},this);
siblings.forEach(function(input){
input.disabled = true;
});
form.reportValidity();
siblings.forEach(function(input){
input.disabled = false;
});
if (tmpForm) {
tmpForm.before(this);
tmpForm.remove();
}
this.focus();
this.selectionStart = 0;
return false;
};
}
Although as far as I know html5 validation doesn't work without a form tag anyway. So it probably isn't necessary to support inputs that aren't inside form tags.
Also the focus() in my implementation is a fallback. The submit/reportValidity already does this. I could probably remove it entirely.
My Polyfill works at least in IE.
I use this.form and if this.form is undefined, I wrap it into a newly created form.
So this.form is always defined.
I don't know exactly how it is in the specification, but validation works without forms in current browsers:
https://jsfiddle.net/7jode1g5/
focus() and selectionstart=0 is needed in IE11
In line 19 you are definingvar tmpForm
, but it's already defined 2 lines above.
I recommend wrapping all that code in:
if (typeof HTMLFormElement !== 'undefined') {
// your polyfill
}
So then it'll be also compatible with server side rendering.
this is the form version, which and seems to work in IE11, and accounts for the case the form has a novalidate attribute, in which case the form would submit.
https://gist.github.com/mcshaz/c65040c11e6daffe356cbedb7ec84ce4
Is there anyway to intercept or listen if reportValidity
has been called?
I'm curious why we couldn't call
submit()
if it's invalid and avoid shuffling buttons:Calling
this.checkValidity()
should make sure we don't callthis.submit()
when it's valid, so it will only cause the validation messages to appear.