@govuk-pay/pay-js-commons
Version:
Reusable js scripts for GOV.UK Pay Node.js projects
108 lines (106 loc) • 4.11 kB
JavaScript
;
// NPM Dependencies
var every = require('lodash/every');
// Local Dependencies
var checks = require('../../utils/field-validation-checks');
exports.enableFieldValidation = function () {
var allForms = Array.prototype.slice.call(document.getElementsByTagName('form'));
allForms.filter(function (form) {
return form.hasAttribute('data-validate');
}).map(function (form) {
return form.addEventListener('submit', initValidation, false);
});
};
function initValidation(e) {
var form = e.target;
e.preventDefault();
clearPreviousErrors();
var validatedFields = findFields(form).map(function (field) {
return validateField(form, field);
});
if (every(validatedFields)) {
form.submit();
} else {
populateErrorSummary(form);
}
}
function clearPreviousErrors() {
var previousErrorsMessages = Array.prototype.slice.call(document.querySelectorAll('.error-message, .error-summary'));
var previousErrorsFields = Array.prototype.slice.call(document.querySelectorAll('.form-group.error'));
previousErrorsMessages.map(function (error) {
return error.remove();
});
previousErrorsFields.map(function (errorField) {
return errorField.classList.remove('error');
});
}
function findFields(form) {
var formFields = Array.prototype.slice.call(form.querySelectorAll('input, textarea, select'));
return formFields.filter(function (field) {
return field.hasAttribute('data-validate');
});
}
function validateField(form, field) {
var result;
var validationTypes = field.getAttribute('data-validate').split(' ');
validationTypes.forEach(function (validationType) {
switch (validationType) {
case 'required':
result = checks.isEmpty(field.value);
break;
case 'currency':
result = checks.isCurrency(field.value);
break;
case 'email':
result = checks.isValidEmail(field.value);
break;
case 'phone':
result = checks.isPhoneNumber(field.value);
break;
case 'https':
result = checks.isHttps(field.value);
break;
case 'belowMaxAmount':
result = checks.isAboveMaxAmount(field.value);
break;
case 'passwordLessThanTenChars':
result = checks.isPasswordLessThanTenChars(field.value);
break;
case 'isFieldGreaterThanMaxLengthChars':
result = checks.isFieldGreaterThanMaxLengthChars(field.value, field.getAttribute('data-validate-max-length'));
break;
case 'isNaxsiSafe':
result = checks.isNaxsiSafe(field.value);
break;
default:
result = false;
break;
}
if (result) {
applyErrorMessaging(form, field, result);
}
});
return !field.closest('.form-group').classList.contains('error');
}
function applyErrorMessaging(form, field, result) {
var formGroup = field.closest('.form-group');
if (!formGroup.classList.contains('error')) {
formGroup.classList.add('error');
document.querySelector('label[for="' + field.id + '"]').insertAdjacentHTML('beforeend', '<span class="error-message">' + result + '</span>');
}
}
function populateErrorSummary(form) {
var erroringFields = Array.prototype.slice.call(form.querySelectorAll('.form-group.error label'));
var errorMessages = erroringFields.map(function (field) {
var id = field.getAttribute('for');
var label = field.innerHTML.split('<')[0].trim();
return {
label: label,
id: id
};
});
form.parentNode.insertAdjacentHTML('afterbegin', "<div id=\"error-summary\" class=\"error-summary\" role=\"group\" aria-labelledby=\"error-summary-heading\" tabindex=\"-1\">\n <h2 class=\"heading-medium error-summary-heading\" id=\"error-summary-heading\">\n There was a problem with the details you gave for:\n </h2>\n <ul class=\"error-summary-list\">\n ".concat(errorMessages.map(function (message) {
return "<li class=\"error-".concat(message.id, "\"><a href=\"#").concat(message.id, "\">").concat(message.label, "</a></li>");
}).join(''), "\n </ul>\n </div>"));
window.scroll(0, 0);
}