Wellidate is a fast, easy-to-use JavaScript form validation library that supports both native HTML5 validation attribute and HTML data attribute.
Download the insert the JavaScript file into the document and we’re ready to go.
<script src="src/wellidate.js"></script>
Apply rules to form fields using HTML5 form validation attributes or HTML data-val-ruleName
attributes as follows:
<form>
<label for="data-name">Name</label>
<input name="data-name" data-val-required="" data-val-length="" data-val-length-max="10">
<button>Submit</button>
</form>
<!-- OR -->
<form>
<label for="data-name">Name</label>
<input name="data-name" required minlength="2" maxlength="10">
<button>Submit</button>
</form>
Initialize the Wellidate on the HTML form and done.
new Wellidate(document.querySelector('form'));
All possible options to customize the form validation. You can pass the following options as an object to the Wellidate method.
new Wellidate(document.querySelector('form'),{
// moves the focus to the invaild field
focusInvalid: true,
// configurable submit handler
submitHandler: null,
// moves the focus to the field after clean up
focusCleanup: false,
// includes the following form fields
include: 'input,textarea,select',
// for displaying results
summary: {
container: '[data-valmsg-summary=true]',
show: function (result) {
if (this.container) {
var summary = document.querySelector(this.container);
if (summary) {
summary.innerHTML = '';
if (result.isValid) {
summary.classList.add('validation-summary-valid');
summary.classList.remove('validation-summary-errors');
} else {
summary.classList.add('validation-summary-errors');
summary.classList.remove('validation-summary-valid');
var list = document.createElement('ul');
result.invalid.forEach(function (invalid) {
var item = document.createElement('li');
item.innerHTML = invalid.message;
list.appendChild(item);
});
summary.appendChild(list);
}
}
}
},
reset: function () {
this.show({
isValid: true,
invalid: []
});
}
},
// default classes
classes: {
inputPending: 'input-validation-pending',
inputError: 'input-validation-error',
inputValid: 'input-validation-valid',
fieldPending: 'input-validation-pending',
fieldError: 'field-validation-error',
fieldValid: 'field-validation-valid',
wasValidated: 'was-validated'
},
// excludes following form fields
excludes: [
'input[type=button]',
'input[type=submit]',
'input[type=image]',
'input[type=reset]',
':disabled'
],
// basic rules
rule: {
trim: true,
message: 'This field is not valid.',
isValid: function () {
return false;
},
isEnabled: function () {
return true;
},
formatMessage: function () {
return this.message;
},
normalizeValue: function (element) {
element = element || this.element;
var value = element.value;
if (element.tagName == 'SELECT' && element.multiple) {
return [].filter.call(element.options, function (option) {
return option.selected;
}).length;
} else if (element.type == 'radio') {
if (element.name) {
var name = this.wellidate.escapeAttribute(element.name);
var checked = document.querySelector('input[name="' + name + '"]:checked');
value = checked ? checked.value : '';
} else {
value = element.checked ? value : '';
}
} else if (element.type == 'file') {
if (value.lastIndexOf('\\') >= 0) {
value = value.substring(value.lastIndexOf('\\') + 1);
} else if (value.lastIndexOf('/') >= 0) {
value = value.substring(value.lastIndexOf('/') + 1);
}
}
return this.trim ? value.trim() : value;
}
}
});
Default validation rules. Override the following validation rules as per your needs.
new Wellidate(document.querySelector('form'),{
rules: {
required: {
message: 'This field is required.',
isValid: function () {
return Boolean(this.normalizeValue());
}
},
equalto: {
message: 'Please enter the same value again.',
isValid: function () {
var other = document.getElementById(this.other);
return other && this.normalizeValue() == this.normalizeValue(other);
}
},
length: {
message: 'Please enter a value between {0} and {1} characters long.',
isValid: function () {
var length = this;
var value = length.normalizeValue();
return (length.min == null || length.min <= value.length) && (value.length <= length.max || length.max == null);
},
formatMessage: function () {
var length = this;
if (length.min != null && length.max == null && !length.isDataMessage) {
return Wellidate.prototype.rules.minlength.message.replace('{0}', length.min);
} else if (length.min == null && length.max != null && !length.isDataMessage) {
return Wellidate.prototype.rules.maxlength.message.replace('{0}', length.max);
}
return length.message.replace('{0}', length.min).replace('{1}', length.max);
}
},
minlength: {
message: 'Please enter at least {0} characters.',
isValid: function () {
return this.min == null || !parseFloat(this.min) <= this.normalizeValue().length;
},
formatMessage: function () {
return this.message.replace('{0}', this.min);
}
},
maxlength: {
message: 'Please enter no more than {0} characters.',
isValid: function () {
return this.normalizeValue().length <= this.max || !parseFloat(this.max);
},
formatMessage: function () {
return this.message.replace('{0}', this.max);
}
},
email: {
message: 'Please enter a valid email address.',
isValid: function () {
return /^$|^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test(this.normalizeValue());
}
},
integer: {
message: 'Please enter a valid integer value.',
isValid: function () {
return /^$|^[+-]?\d+$/.test(this.normalizeValue());
}
},
number: {
message: 'Please enter a valid number.',
scaleMessage: 'Please enter a value with no more than {0} fractional digits',
precisionMessage: 'Please enter a value using no more than {0} significant digits',
isValid: function () {
return /^$|^[+-]?(\d+|\d{1,3}(,\d{3})+)?(\.\d+)?$/.test(this.normalizeValue());
}
},
digits: {
message: 'Please enter only digits.',
isValid: function () {
return /^\d*$/.test(this.normalizeValue());
}
},
date: {
message: 'Please enter a valid date.',
isValid: function () {
return /^$|^\d{4}-(0?[1-9]|1[012])-(0?[1-9]|[12][0-9]|3[01])$/.test(this.normalizeValue());
}
},
range: {
message: 'Please enter a value between {0} and {1}.',
isValid: function () {
var range = this;
var value = range.normalizeValue2();
return !value || (range.min == null || range.min <= parseFloat(value)) && (parseFloat(value) <= range.max || range.max == null);
},
formatMessage: function () {
var range = this;
if (range.min != null && range.max == null && !range.isDataMessage) {
return Wellidate.prototype.rules.min.message.replace('{0}', range.min);
} else if (range.min == null && range.max != null && !range.isDataMessage) {
return Wellidate.prototype.rules.max.message.replace('{0}', range.max);
}
return range.message.replace('{0}', range.min).replace('{1}', range.max);
}
},
min: {
message: 'Please enter a value greater than or equal to {0}.',
isValid: function () {
var value = this.normalizeValue();
return !value || !parseFloat(this.value) || this.value <= parseFloat(value);
},
formatMessage: function () {
return this.message.replace('{0}', this.value);
}
},
max: {
message: 'Please enter a value less than or equal to {0}.',
isValid: function () {
var value = this.normalizeValue();
return !value || !parseFloat(this.value) || parseFloat(value) <= this.value;
},
formatMessage: function () {
return this.message.replace('{0}', this.value);
}
},
greater: {
message: 'Please enter a value greater than {0}.',
isValid: function () {
var value = this.normalizeValue();
return !value || !parseFloat(this.than) || this.than < parseFloat(value);
},
formatMessage: function () {
return this.message.replace('{0}', this.than);
}
},
lower: {
message: 'Please enter a value lower than {0}.',
isValid: function () {
var value = this.normalizeValue();
return !value || !parseFloat(this.than) || parseFloat(value) < this.than;
},
formatMessage: function () {
return this.message.replace('{0}', this.than);
}
},
step: {
message: 'Please enter a multiple of {0}.',
isValid: function () {
var value = this.normalizeValue();
return !value || !parseFloat(this.value) || parseFloat(value) % this.value == 0;
},
formatMessage: function () {
return this.message.replace('{0}', this.value);
}
},
filesize: {
page: 1024,
message: 'File size should not exceed {0} MB.',
isValid: function () {
var size = [].reduce.call(this.element.files, function (total, file) {
return total + file.size;
}, 0);
return size <= this.max || this.max == null;
},
formatMessage: function () {
var filesize = this;
var mb = (filesize.max / filesize.page / filesize.page).toFixed(2);
return filesize.message.replace('{0}', mb.replace(/[.|0]*$/, ''));
}
},
accept: {
message: 'Please select files in correct format.',
isValid: function () {
var filter = this.types.split(',').map(function (type) {
return type.trim();
});
var correct = [].filter.call(this.element.files, function (file) {
var extension = file.name.split('.').pop();
for (var i = 0; i < filter.length; i++) {
if (filter[i].indexOf('.') == 0) {
if (file.name != extension && '.' + extension == filter[i]) {
return true;
}
} else if (/\/\*$/.test(filter[i])) {
if (file.type.indexOf(filter[i].replace(/\*$/, '')) == 0) {
return true;
}
} else if (file.type == filter[i]) {
return true;
}
}
return !filter.length;
});
return this.element.files.length == correct.length;
}
},
regex: {
message: 'Please enter value in a valid format. {0}',
isValid: function () {
var value = this.normalizeValue();
return !value || !this.pattern || new RegExp(this.pattern).test(value);
},
formatMessage: function () {
return this.message.replace('{0}', this.title || '');
}
},
remote: {
type: 'get',
message: 'Please fix this field.',
isValid: function (validatable) {
var remote = this;
if (remote.request && remote.request.readyState != 4) {
remote.request.abort();
}
clearTimeout(remote.start);
remote.start = setTimeout(function () {
if (validatable.isValid) {
remote.request = new XMLHttpRequest();
remote.request.open(remote.type, remote.buildUrl(), true);
remote.request.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
remote.request.onload = function () {
if (validatable.isValid && 200 <= this.status && this.status < 400) {
remote.apply(validatable, this.responseText);
}
};
remote.prepare(validatable);
remote.request.send();
validatable.pending();
}
}, 1);
return true;
},
buildUrl: function () {
var remote = this;
var url = remote.url.split('?', 2)[0];
var fields = (remote.additionalFields || '').split(',').filter(Boolean);
var query = (remote.url.split('?', 2)[1] || '').split('&').filter(Boolean);
for (var i = 0; i < fields.length; i++) {
var element = document.querySelector(fields[i]);
var value = remote.normalizeValue(element) || '';
query.push(encodeURIComponent(element.name) + "=" + encodeURIComponent(value));
}
query.push(encodeURIComponent(remote.element.name) + "=" + encodeURIComponent(remote.normalizeValue() || ''));
return url + '?' + query.join('&');
},
prepare: function () {
},
apply: function (validatable, response) {
var result = JSON.parse(response);
if (result.isValid === false) {
validatable.error('remote', result.message);
} else {
validatable.success(result.message);
}
}
}
}
});
API methods.
var instance = new Wellidate(document.querySelector('form'));
// checks if is valid
instance.isValid(fieldName);
// Validates all or selected fields
instance.form();
// Validates the form and returns the validation results for each field
instance.validate();
// rebuilds the instnace
instance.rebuild();
// applies rules to fields
instance.apply({
'#name': {
error: 'Enter a unique name'
},
// ...
});
// resets the form
instance.reset();
Author: NonFactors
Demo: https://nonfactors.github.io/Wellidate/
Source Code: https://github.com/NonFactors/Wellidate
#javascript