hyperform
Version:
Capture form validation back from the browser
93 lines (77 loc) • 2.82 kB
JavaScript
import { do_filter } from '../components/hooks';
import { validation_candidates, non_inputs } from '../components/types';
import { get_wrapper } from '../components/wrapper';
import get_type from '../tools/get_type';
/**
* check if an element should be ignored due to any of its parents
*
* Checks <fieldset disabled> and <datalist>.
*/
function is_in_disallowed_parent(element) {
let p = element.parentNode;
while (p && p.nodeType === 1) {
if (p instanceof window.HTMLFieldSetElement &&
p.hasAttribute('disabled')) {
/* quick return, if it's a child of a disabled fieldset */
return true;
} else if (p.nodeName.toUpperCase() === 'DATALIST') {
/* quick return, if it's a child of a datalist
* Do not use HTMLDataListElement to support older browsers,
* too.
* @see https://html.spec.whatwg.org/multipage/forms.html#the-datalist-element:barred-from-constraint-validation
*/
return true;
} else if (p === element.form) {
/* the outer boundary. We can stop looking for relevant elements. */
break;
}
p = p.parentNode;
}
return false;
}
/**
* check if an element is a candidate for constraint validation
*
* @see https://html.spec.whatwg.org/multipage/forms.html#barred-from-constraint-validation
*/
export default function(element) {
/* allow a shortcut via filters, e.g. to validate type=hidden fields */
const filtered = do_filter('is_validation_candidate', null, element);
if (filtered !== null) {
return !! filtered;
}
/* it must be any of those elements */
if (element instanceof window.HTMLSelectElement
||
element instanceof window.HTMLTextAreaElement
||
element instanceof window.HTMLButtonElement
||
element instanceof window.HTMLInputElement) {
const type = get_type(element);
/* its type must be in the whitelist */
if (non_inputs.indexOf(type) > -1 ||
validation_candidates.indexOf(type) > -1) {
/* it mustn't be disabled or readonly */
if (! element.hasAttribute('disabled') &&
! element.hasAttribute('readonly')) {
const wrapped_form = get_wrapper(element);
if (
/* the parent form doesn't allow non-standard "novalidate" attributes... */
(wrapped_form && ! wrapped_form.settings.novalidateOnElements) ||
/* ...or it doesn't have such an attribute/property */
(! element.hasAttribute('novalidate') && ! element.noValidate)
) {
/* it isn't part of a <fieldset disabled> */
if (! is_in_disallowed_parent(element)) {
/* then it's a candidate */
return true;
}
}
}
}
}
/* this is no HTML5 validation candidate... */
return false;
}
;