@stormid/validate
Version:
Client-side form validation
3 lines (2 loc) • 17.5 kB
JavaScript
function e(){return e=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var n in r)({}).hasOwnProperty.call(r,n)&&(e[n]=r[n])}return e},e.apply(null,arguments)}var t,r="SET_INITIAL_STATE",n="CLEAR_ERRORS",u="VALIDATION_ERRORS",a="VALIDATION_ERROR",i="CLEAR_ERROR",o="ADD_VALIDATION_METHOD",s="ADD_GROUP",c="REMOVE_GROUP",l="START_REALTIME",d="data-valmsg-for",g=["remote-additionalfields","equalto-other"],f={length:["length-min","length-max"],stringlength:["length-max"],range:["range-min","range-max"],min:["min-min"],max:["max-max"],minlength:["minlength-min"],maxlength:["maxlength-max"],regex:["regex-pattern"],equalto:["equalto-other"],remote:["remote-url","remote-additionalfields","remote-type"]},m=["required","stringlength","dateISO","regex","digits","email","number","url","length","min","max","minlength","maxlength","range","equalto","remote"],p="field-validation-valid",b="error-message",v="group",h=((t={})[r]=function(e,t){return Object.assign({},e,t)},t[n]=function(e){return Object.assign({},e,{groups:Object.keys(e.groups).reduce(function(t,r){return t[r]=Object.assign({},e.groups[r],{errorMessages:[],valid:!0}),t},{})})},t[i]=function(e,t){var r={};return r[t]=Object.assign({},e.groups[t],{errorMessages:[],valid:!0}),Object.assign({},e,{groups:Object.assign({},e.groups,r)})},t[s]=function(e,t,r){return Object.assign({},e,{groups:Object.assign({},e.groups,t),errors:Object.assign({},e.errors,r)})},t[c]=function(t,r){return Object.assign({},t,e({groups:Object.keys(t.groups).reduce(function(e,n){return n!==r&&(e[n]=t.groups[n]),e},{})},void 0!==t.errors?{errors:Object.keys(t.errors).reduce(function(e,n){return n!==r&&(e[n]=t.errors[n]),e},{})}:{}))},t[o]=function(e,t){var r,n=Object.assign({},e.groups[t.groupName]?e.groups[t.groupName]:{},e.groups[t.groupName]?{validators:[].concat(e.groups[t.groupName].validators,[t.validator])}:{fields:t.fields||(document.querySelector('[data-val-group="'+t.groupName+'"]')?[].slice.call(document.querySelectorAll('[data-val-group="'+t.groupName+'"]')):[].slice.call(document.getElementsByName(t.groupName))),serverErrorNode:document.querySelector("["+d+'="'+t.groupName+'"]')||!1,valid:!1,validators:[t.validator]});return Object.assign({},e,{groups:Object.assign({},e.groups,(r={},r[t.groupName]=n,r))})},t[u]=function(e,t){return Object.assign({},e,{realTimeValidation:!0,groups:Object.keys(e.groups).reduce(function(r,n){return r[n]=Object.assign({},e.groups[n],t[n]),r},{})})},t[a]=function(e,t){var r;return Object.assign({},e,{groups:Object.assign({},e.groups,(r={},r[t.group]=Object.assign({},e.groups[t.group],{errorMessages:t.errorMessages,valid:!1}),r))})},t[l]=function(e,t){return Object.assign({},e,t)},t),A=function(e){return/radio|checkbox/i.test(e.type)},y=function(e){return"hidden"===e.getAttribute("type")},E=function(e,t){return A(t)||y(t)||!function(e){return null!=e.value&&e.value.length>0}(t)||(e=t.value.trim()),A(t)&&t.checked&&(Array.isArray(e)?e.push(t.value.trim()):e=[t.value.trim()]),e},x=function(e){return e.map(function(e){return encodeURIComponent(e[0].getAttribute("name"))+"="+encodeURIComponent(O(e))}).join("&")},O=function(e){return Object.prototype.hasOwnProperty.call(e,"fields")?e.fields.reduce(E,""):e.reduce(E,"")},S=function(e){return Object.keys(e).reduce(function(t,r){if(e[r].serverErrorNode){var n=e[r].serverErrorNode.textContent;n&&(t[r]=n)}return t},{})},N=function(e){return!function(e){return e.validators.filter(function(e){return"required"===e.type}).length>0}(e)&&""===O(e)},j=function(e){return function(t){return N(t)||t.fields.reduce(function(t,r){return e.test(r.value)},!1)}},q=function(e,t){return function(r){return N(r)||r.fields.reduce(t(function(e,t){return e.validators.filter(function(e){return e.type===t})[0].params}(r,e)),!1)}},T=function(e){return void 0!==e},R={required:function(e){return""!==O(e)},email:j(/^[A-Za-zŽžÀ-ÿŠ0-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])?)*$/),url:j(/^(?:(?:(?:https?|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-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i),dateISO:j(/^\d{4}[/-](0?[1-9]|1[012])[/-](0?[1-9]|[12][0-9]|3[01])$/),number:j(/^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/),digits:j(/^\d+$/),minlength:q("minlength",function(e){return function(t,r){return+r.value.length>=+e.min}}),maxlength:q("maxlength",function(e){return function(t,r){return+r.value.length<=+e.max}}),equalto:q("equalto",function(e){return function(t,r){return e.other.reduce(function(e,t){return O(t)!==r.value&&(e=!1),e},!0)}}),pattern:q("pattern",function(e){return function(t,r){return RegExp(e.regex).test(r.value)}}),regex:q("regex",function(e){return function(t,r){return RegExp(e.pattern).test(r.value)}}),min:q("min",function(e){return function(t,r){return!isNaN(parseInt(r.value,10))&&+r.value>=+e.min}}),max:q("max",function(e){return function(t,r){return!isNaN(parseInt(r.value,10))&&+r.value<=+e.max}}),stringlength:q("stringlength",function(e){return function(t,r){return+r.value.length<=+e.max}}),length:q("length",function(e){return function(t,r){return+r.value.length>=+e.min&&(void 0===e.max||+r.value.length<=+e.max)}}),range:q("range",function(e){return function(t,r){return(!T(e.min)||+r.value>=+e.min)&&(!T(e.max)||+r.value<=+e.max)}}),remote:function(e,t){return new Promise(function(r,n){var u,a,i,o=O(e);(a="get"!==t.type?t.url:t.url+"?"+e.fields[0].name+"="+o+"&"+x(t.additionalfields),i={method:t.type&&t.type.toUpperCase()||"POST",body:"get"!==t.type?JSON.stringify((u={},u[e.fields[0].name]=o,u)):x(t.additionalfields),headers:{"Content-Type":"application/x-www-form-urlencoded;charset=UTF-8"}},new Promise(function(e,t){var r=new XMLHttpRequest;r.open(i.method||"GET",a),i.headers&&Object.keys(i.headers).forEach(function(e){r.setRequestHeader(e,i.headers[e])}),r.onload=function(){r.status>=200&&r.status<300?e(r.response):t(r.statusText)},r.onerror=function(){return t(r.statusText)},r.send(i.body)})).then(function(e){return r(e)})})},custom:function(e,t){return N(t)||e(O(t),t.fields)}},w=function(e,t){return!!f[t]&&{params:f[t].reduce(function(t,r){return e.hasAttribute("data-val-"+r)?Object.assign(t,function(e,t){var r,n=t.getAttribute("data-val-"+e);return(r={})[e.split("-")[1]]=~g.indexOf(e)?n.split(",").map(function(e){return[].slice.call(document.querySelectorAll("[name="+function(e){return e.replace(/([!"#$%&'()*+,./:;<=>?@[\\\]^`{|}~])/g,"\\$1")}(e)+"]"))}):n,r}(r,e)):t},{})}},L=function(e,t){return e.getAttribute("data-val-"+t)?{message:e.getAttribute("data-val-"+t)}:{}},k=function(t){return"true"===t.getAttribute("data-val")?function(e){return m.reduce(function(t,r){return e.getAttribute("data-val-"+r)?[].concat(t,[Object.assign({type:r,message:e.getAttribute("data-val-"+r)},w(e,r))]):t},[])}(t):function(t){var r=[];return!t.hasAttribute("required")&&!t.hasAttribute("aria-required")||"false"===t.getAttribute("required")&&"false"===t.getAttribute("aria-required")||r.push(e({type:"required"},L(t,"required"))),"email"===t.getAttribute("type")&&r.push(e({type:"email"},L(t,"email"))),"url"===t.getAttribute("type")&&r.push(e({type:"url"},L(t,"url"))),"number"===t.getAttribute("type")&&r.push(e({type:"number"},L(t,"number"))),t.getAttribute("minlength")&&"false"!==t.getAttribute("minlength")&&r.push(e({type:"minlength",params:{min:t.getAttribute("minlength")}},L(t,"minlength"))),t.getAttribute("maxlength")&&"false"!==t.getAttribute("maxlength")&&r.push(e({type:"maxlength",params:{max:t.getAttribute("maxlength")}},L(t,"maxlength"))),t.getAttribute("min")&&"false"!==t.getAttribute("min")&&r.push(e({type:"min",params:{min:t.getAttribute("min")}},L(t,"min"))),t.getAttribute("max")&&"false"!==t.getAttribute("max")&&r.push(e({type:"max",params:{max:t.getAttribute("max")}},L(t,"max"))),t.getAttribute("pattern")&&"false"!==t.getAttribute("pattern")&&r.push(e({type:"pattern",params:{regex:t.getAttribute("pattern")}},L(t,"pattern"))),r}(t)},M=function(e,t){var r=t.getAttribute("data-val-"+v)?t.getAttribute("data-val-"+v):t.getAttribute("name");if(!r)return console.warn("Missing data group or name attribute"),e;if(e[r]&&y(t))return e;var n=document.querySelector("["+d+'="'+r+'"]')||!1;return e[r]=e[r]?Object.assign(e[r],{fields:[].concat(e[r].fields,[t])}):{valid:!1,validators:k(t),fields:[t],serverErrorNode:n},e},I=function(e,t){return function(r,n,u){return!0===n?r:[].concat(r,["boolean"==typeof n?(a=t.settings.messages,i=t.groups[e].validators[u],i.message||a[i.type](void 0!==i.params?i.params:null)):n]);var a,i}},P=function(e){var t={};for(var r in e)e[r].validators.length>0&&!e[r].fields.reduce(function(e,t){return"hidden"!==t.type&&(e=!1),e},!0)&&(t[r]=e[r]);return t},C=function(e,t){return!0!==t&&(e=!1),e},z=function(e){return e.fields.reduce(function(e,t){return t.hasAttribute("disabled")&&"false"!==t.getAttribute("disabled")&&(e=!0),e},!1)?Promise.resolve([!0]):Promise.all(e.validators.map(function(t){return new Promise(function(r,n){(function(e,t){return new Promise(function(r,n){try{r("custom"===t.type?R.custom(t.method,e):R[t.type](e,t.params))}catch(e){console.warn(e),r(e)}})})(e,t).then(function(e){"true"!==String(e)?r("false"!==String(e)&&e):r(!0)}).catch(function(e){return console.warn(e)})})}))},_=function(e){return function(t){t.groups[e].serverErrorNode?(t.groups[e].serverErrorNode.innerHTML="",t.groups[e].serverErrorNode.classList.remove(b),t.groups[e].serverErrorNode.classList.add(p)):t.errors[e].parentNode.removeChild(t.errors[e]),t.groups[e].fields.forEach(function(r){r.parentNode.classList.remove("is--invalid"),r.removeAttribute("aria-invalid");var n=(t.groups[e].serverErrorNode||t.errors[e]).id;r.hasAttribute("aria-describedby")&&(r.getAttribute("aria-describedby")===n?r.removeAttribute("aria-describedby"):r.setAttribute("aria-describedby",r.getAttribute("aria-describedby").replace(" "+n,"")))}),delete t.errors[e]}},D=function(e){e.errors&&Object.keys(e.errors).forEach(function(t){_(t)(e)})},H=function(e){Object.keys(e.groups).forEach(function(t){e.groups[t].valid||V(t)(e)})},V=function(e){return function(t){t.errors[e]&&_(e)(t);var r=function(e,t){var r=e.groups[t].errorMessages[0],n=e.groups[t].fields.reduce(function(e,t,r,n){return r===n.length-1?e+t.value:t.value+", "},"");return r.replace("{{value}}",n)}(t,e);if(t.groups[e].serverErrorNode)t.errors[e]=function(e,t){var r=document.createTextNode(t);return e.serverErrorNode.classList.remove(p),e.serverErrorNode.classList.add(b),e.serverErrorNode.appendChild(r)}(t.groups[e],r);else{var n=document.querySelector('[for="'+t.groups[e].fields[t.groups[e].fields.length-1].getAttribute("id")+'"]');if(null===n)return void console.error("No matching HTML label or server error node found for validation group: "+e+". Error message: '"+r+"' cannot be displayed. Form will not be submitted.");t.errors[e]=n.parentNode.insertBefore(function(e,t,r){var n=document.createElement("span");for(var u in t)n.setAttribute(u,t[u]);return void 0!==r&&r.length&&n.appendChild(document.createTextNode(r)),n}(0,{class:b,id:e+"-error-message"},r),n.nextSibling)}var u=t.groups[e].serverErrorNode||t.errors[e];t.groups[e].fields.forEach(function(e){e.parentNode.classList.add("is--invalid"),e.setAttribute("aria-invalid","true"),e.hasAttribute("aria-describedby")&&$(e,u.getAttribute("id"))||e.setAttribute("aria-describedby",e.hasAttribute("aria-describedby")?e.getAttribute("aria-describedby")+" "+u.getAttribute("id"):u.getAttribute("id"))})}},$=function(e,t){var r=e.getAttribute("aria-describedby").split(" ");return r.length>0&&r.reduce(function(e,r){return e||r===t},!1)},G=function(e){var t=Object.keys(e.groups).reduce(function(t,r){return t||e.groups[r].valid||(t=e.groups[r].fields[0]),t},!1);t&&t.focus()},U=function(e){Object.keys(e.groups).forEach(function(t){var r;e.groups[t].serverErrorNode&&!e.groups[t].serverErrorNode.hasAttribute("id")&&e.groups[t].serverErrorNode.setAttribute("id",t+"-error-message"),(r=e.groups[t].fields).forEach(function(e){(e.hasAttribute("required")||e.hasAttribute("data-val-required"))&&("radio"!==e.getAttribute("type")&&"checkbox"!==e.getAttribute("type")||"checkbox"===e.getAttribute("type")&&1===r.length)&&e.setAttribute("aria-required","true")})})},Z=function(t){var r=function(e){return function(){var r=t.getState(),n=r.groups;!n[e].valid&&r.errors[e]&&t.update(h[i](t.getState(),e),[_(e)]),z(n[e]).then(function(r){r.reduce(C,!0)||t.update(h[a](t.getState(),{group:e,errorMessages:r.reduce(I(e,t.getState()),[])}),[V(e)])})}};Object.keys(t.getState().groups).forEach(function(n){var u=e({},t.getState().groups);if(!u[n].hasEvent){u[n].fields.forEach(function(e){e.addEventListener(function(e){return["input","change"][Number(A(e)||(t=e,"select"===t.nodeName.toLowerCase())||function(e){return"file"===e.getAttribute("type")}(e))];var t}(e),r(n))});var a=u[n].validators.filter(function(e){return"equalto"===e.type});a.length>0&&a[0].params.other.forEach(function(e){e.forEach(function(e){e.addEventListener("blur",r(n))})}),u[n].hasEvent=!0}t.update(h[l](t.getState(),{groups:u}))})},B=function(e){return function(t){return t&&t.preventDefault(),e.update(h[n](e.getState()),[D]),new Promise(function(r){var n=e.getState(),a=n.groups,i=n.realTimeValidation;(function(e){return Promise.all(Object.keys(e).map(function(t){return z(e[t])}))})(a).then(function(o){return function(e){var t;return(t=[]).concat.apply(t,e).reduce(C,!0)}(o)?function(e,t,r){var n=r.getState(),u=n.settings,a=n.form,i=!1,o=!1,s=function(){var e;u.submit?u.submit():a.submit(),i&&(e=i).parentNode.removeChild(e),o&&a.setAttribute("action",o)};return Array.from(a.querySelectorAll('[type="submit"]')).forEach(function(e){var t;(t=e).hasAttribute("name")&&t.hasAttribute("value")&&(i=function(e,t){var r=document.createElement("input");return r.setAttribute("type","hidden"),r.setAttribute("name",e.getAttribute("name")),r.setAttribute("value",e.getAttribute("value")),t.appendChild(r)}(e,a)),function(e){return e.hasAttribute("formaction")&&""!==e.getAttribute("formaction")}(e)&&(o=a.getAttribute("action"),a.setAttribute("action",e.getAttribute("formaction")))}),e&&e.target&&(u.preSubmitHook?(u.preSubmitHook(),window.setTimeout(s,16)):s()),t(!0)}(t,r,e):(!1===i&&Z(e),e.update(h[u](e.getState(),Object.keys(a).reduce(function(e,t,r){return e[t]={valid:o[r].reduce(C,!0),errorMessages:o[r].reduce(I(t,n),[])},e},{})),[H,G]),r(!1))}).catch(function(e){return console.warn(e)})})}},F=function(e){return function(t,r,n,u){if(void 0===t||void 0===r||void 0===n||!e.getState()[t]&&0===document.getElementsByName(t).length&&0===[].slice.call(document.querySelectorAll('[data-val-group="'+t+'"]')).length&&!u)return console.warn("Custom validation method cannot be added.");e.update(h[o](e.getState(),{groupName:t,fields:u,validator:{type:"custom",method:r,message:n}}))}},J=function(e){return function(t){var r=P(t.reduce(M,{}));if(0===Object.keys(r).length)return console.warn("Group cannot be added.");e.update(h[s](e.getState(),r,S(r)),[U,function(){e.getState().realTimeValidation&&Z(e)}])}},X=function(e){return function(t){return new Promise(function(r){!e.getState().groups[t].valid&&e.getState().errors[t]&&e.update(h[i](e.getState(),t),[_(t)]),z(e.getState().groups[t]).then(function(n){return n.reduce(C,!0)?r(!0):(e.update(h[a](e.getState(),{group:t,errorMessages:n.reduce(I(t,e.getState()),[])}),[V(t)]),r(!1))})})}},Y=function(e){return function(t){var r=e.getState();r.errors[t]&&_(t)(r),e.update(h[c](e.getState(),t))}},K={messages:{required:function(){return"You must answer this question."},email:function(){return"Enter a valid email address, for example: example@example.com."},pattern:function(){return"The value must match the pattern"},url:function(){return"Enter a valid URL"},number:function(){return"Enter a valid number"},maxlength:function(e){return"Enter no more than "+e.max+" characters"},minlength:function(e){return"Enter at least "+e.min+" characters"},max:function(e){return"Enter a number lower than or equal to "+e.max},min:function(e){return"Enter a number higher than or equal to "+e.min}}},Q=function(t,u){var a=function(e){return"string"==typeof e?[].slice.call(document.querySelectorAll(e)):e instanceof Array?e:Object.prototype.isPrototypeOf.call(NodeList.prototype,e)?[].slice.call(e):e instanceof HTMLElement?[e]:[]}(t);return a.reduce(function(t,a){return a.hasAttribute("novalidate")||(t.push(Object.create((i=a,o=e({},K,u),s={},(c={update:function(e,t){s=null!=e?e:s,t&&t.forEach(function(e){return e(s)})},getState:function(){return s}}).update(h[r](function(e,t){var r=P([].slice.call(e.querySelectorAll("input:not([type=submit]), textarea, select")).reduce(M,{}));return{form:e,settings:t,errors:S(r),realTimeValidation:!1,groups:r}}(i,o)),[U]),i.addEventListener("submit",B(c)),i.addEventListener("reset",function(){return c.update(h[n](c.getState()),[D])}),{getState:c.getState,validate:B(c),addMethod:F(c),addGroup:J(c),validateGroup:X(c),removeGroup:Y(c)}))),a.setAttribute("novalidate","novalidate")),t;var i,o,s,c},[])};export{Q as default};
//# sourceMappingURL=index.modern.js.map