Skip to content
This repository has been archived by the owner on Nov 10, 2018. It is now read-only.

Commit

Permalink
Merge pull request #25 from FloEdelmann/fallback
Browse files Browse the repository at this point in the history
Use browser's validation if available
  • Loading branch information
cferdinandi authored Sep 29, 2017
2 parents 9491b7b + f2fb083 commit c878215
Show file tree
Hide file tree
Showing 10 changed files with 196 additions and 19 deletions.
11 changes: 10 additions & 1 deletion dist/js/validate.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@

// Messages
messageValueMissing: 'Please fill out this field.',
messageValueMissingSelect: 'Please select a value.',
messageValueMissingSelectMulti: 'Please select at least one value.',
messageTypeMismatchEmail: 'Please enter an email address.',
messageTypeMismatchURL: 'Please enter a URL.',
messageTooShort: 'Please lengthen this text to {minLength} characters or more. You are currently using {length} characters.',
Expand Down Expand Up @@ -160,7 +162,14 @@
if (validity.valid) return;

// If field is required and empty
if (validity.valueMissing) return localSettings.messageValueMissing;
if (validity.valueMissing) {

if (field.type === 'select-multiple') return localSettings.messageValueMissingSelectMulti;

if (field.type === 'select-one') return localSettings.messageValueMissingSelect;

return localSettings.messageValueMissing;
}

// If not the right type
if (validity.typeMismatch) {
Expand Down
2 changes: 1 addition & 1 deletion dist/js/validate.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

58 changes: 54 additions & 4 deletions dist/js/validityState-polyfill.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,30 @@
return ('validity' in input && 'badInput' in input.validity && 'patternMismatch' in input.validity && 'rangeOverflow' in input.validity && 'rangeUnderflow' in input.validity && 'stepMismatch' in input.validity && 'tooLong' in input.validity && 'tooShort' in input.validity && 'typeMismatch' in input.validity && 'valid' in input.validity && 'valueMissing' in input.validity);
};

// Save browser's own implementation if available
var browserValidityFunctions = (function() {
var inputValidity = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'validity');
var buttonValidity = Object.getOwnPropertyDescriptor(HTMLButtonElement.prototype, 'validity');
var selectValidity = Object.getOwnPropertyDescriptor(HTMLSelectElement.prototype, 'validity');
var textareaValidity = Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype, 'validity');

var functions = {};
if (inputValidity) {
functions.input = inputValidity.get;
}
if (buttonValidity) {
functions.button = buttonValidity.get;
}
if (selectValidity) {
functions.select = selectValidity.get;
}
if (textareaValidity) {
functions.textarea = textareaValidity.get;
}

return functions;
})();

/**
* Generate the field validity object
* @param {Node]} field The field to validate
Expand All @@ -23,7 +47,7 @@
var getValidityState = function (field) {

// Variables
var type = field.getAttribute('type') || input.nodeName.toLowerCase();
var type = field.getAttribute('type') || field.nodeName.toLowerCase();
var isNum = type === 'number' || type === 'range';
var length = field.value.length;
var valid = true;
Expand All @@ -43,24 +67,32 @@

// Run validity checks
var checkValidity = {
badInput: (isNum && length > 0 && !/[-+]?[0-9]/.test(field.value)), // value of a number field is not a number
badInput: (isNum && length > 0 && !/^[-+]?(?:\d+|\d*[.,]\d+)$/.test(field.value)), // value of a number field is not a number
patternMismatch: (field.hasAttribute('pattern') && length > 0 && new RegExp(field.getAttribute('pattern')).test(field.value) === false), // value does not conform to the pattern
rangeOverflow: (field.hasAttribute('max') && isNum && field.value > 0 && Number(field.value) > Number(field.getAttribute('max'))), // value of a number field is higher than the max attribute
rangeUnderflow: (field.hasAttribute('min') && isNum && field.value > 0 && Number(field.value) < Number(field.getAttribute('min'))), // value of a number field is lower than the min attribute
stepMismatch: (isNum && ((field.hasAttribute('step') && field.getAttribute('step') !== 'any' && Number(field.value) % Number(field.getAttribute('step')) !== 0) || (!field.hasAttribute('step') && Number(field.value) % 1 !== 0))), // value of a number field does not conform to the stepattribute
tooLong: (field.hasAttribute('maxLength') && field.getAttribute('maxLength') > 0 && length > parseInt(field.getAttribute('maxLength'), 10)), // the user has edited a too-long value in a field with maxlength
tooShort: (field.hasAttribute('minLength') && field.getAttribute('minLength') > 0 && length > 0 && length < parseInt(field.getAttribute('minLength'), 10)), // the user has edited a too-short value in a field with minlength
typeMismatch: (length > 0 && ((type === 'email' && !/^([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x22([^\x0d\x22\x5c\x80-\xff]|\x5c[\x00-\x7f])*\x22)(\x2e([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x22([^\x0d\x22\x5c\x80-\xff]|\x5c[\x00-\x7f])*\x22))*\x40([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x5b([^\x0d\x5b-\x5d\x80-\xff]|\x5c[\x00-\x7f])*\x5d)(\x2e([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x5b([^\x0d\x5b-\x5d\x80-\xff]|\x5c[\x00-\x7f])*\x5d))*$/.test(field.value)) || (type === 'url' && !/^(?:(?:https?|HTTPS?|ftp|FTP):\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-zA-Z\u00a1-\uffff0-9]-*)*[a-zA-Z\u00a1-\uffff0-9]+)(?:\.(?:[a-zA-Z\u00a1-\uffff0-9]-*)*[a-zA-Z\u00a1-\uffff0-9]+)*)(?::\d{2,5})?(?:[\/?#]\S*)?$/.test(field.value)))), // value of a email or URL field is not an email address or URL
valueMissing: (field.hasAttribute('required') && (((type === 'checkbox' || type === 'radio') && !field.checked) || (type === 'select' && field.options[field.selectedIndex].value < 1) || (type !=='checkbox' && type !== 'radio' && type !=='select' && length < 1))) // required field without a value
valueMissing: (field.hasAttribute('required') && (((type === 'checkbox' || type === 'radio') && !field.checked) || (type === 'select' && (field.selectedIndex === -1 || field.options[field.selectedIndex].value.length < 1)) || (type !== 'checkbox' && type !== 'radio' && type !=='select' && length < 1))) // required field without a value
};

// Run browser's own validation if available
var fieldTagName = field.tagName.toLowerCase();
var browserValidity = fieldTagName in browserValidityFunctions ? browserValidityFunctions[fieldTagName].call(field) : {};

// Check if any errors
for (var key in checkValidity) {
if (checkValidity.hasOwnProperty(key)) {
// If browser has detected an error, adopt it to our validity object
if (key in browserValidity && browserValidity[key]) {
checkValidity[key] = true;
}

// If there's an error, change valid value
if (checkValidity[key]) {
valid = false;
break;
}
}
}
Expand All @@ -81,6 +113,24 @@
},
configurable: true,
});
Object.defineProperty(HTMLButtonElement.prototype, 'validity', {
get: function ValidityState() {
return getValidityState(this);
},
configurable: true,
});
Object.defineProperty(HTMLSelectElement.prototype, 'validity', {
get: function ValidityState() {
return getValidityState(this);
},
configurable: true,
});
Object.defineProperty(HTMLTextAreaElement.prototype, 'validity', {
get: function ValidityState() {
return getValidityState(this);
},
configurable: true,
});
// }

})(window, document);
Loading

0 comments on commit c878215

Please sign in to comment.