From 77fb5fe19de162f9e97e4a284ac3c52059586c5b Mon Sep 17 00:00:00 2001 From: Nivanka Fonseka Date: Thu, 23 Mar 2023 13:33:08 +1300 Subject: [PATCH] added userforms groups to have the display rules --- client/dist/js/userforms.js | 2 +- client/dist/js/userforms.js.map | 1 - client/src/bundles/UserForms.js | 13 +++- code/Control/UserDefinedFormController.php | 63 +++++++++---------- .../EditableFormField/EditableFieldGroup.php | 7 ++- .../FormField/UserFormsGroupField_holder.ss | 4 +- 6 files changed, 50 insertions(+), 40 deletions(-) delete mode 100644 client/dist/js/userforms.js.map diff --git a/client/dist/js/userforms.js b/client/dist/js/userforms.js index ac7c1e2..3f41eaf 100644 --- a/client/dist/js/userforms.js +++ b/client/dist/js/userforms.js @@ -1 +1 @@ -!function(e){function t(n){if(r[n])return r[n].exports;var i=r[n]={i:n,l:!1,exports:{}};return e[n].call(i.exports,i,i.exports,t),i.l=!0,i.exports}var r={};t.m=e,t.c=r,t.i=function(e){return e},t.d=function(e,r,n){t.o(e,r)||Object.defineProperty(e,r,{configurable:!1,enumerable:!0,get:n})},t.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(r,"a",r),r},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s="./client/src/bundles/bundle.js")}({"./client/src/bundles/UserForms.js":function(e,t,r){"use strict";function n(e){return e&&e.__esModule?e:{default:e}}function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function s(e){return"none"!==e.style.display&&"hidden"!==e.style.visibility&&!e.classList.contains("hide")}var u=function(){function e(e,t){for(var r=0;ra?r(i+" cannot be greater than "+a):e()})});var l=n.getAttribute("data-rule-minlength"),f=n.getAttribute("data-rule-maxlength");null===l&&null===f||(r[n.getAttribute("name")].asyncValidator=function(e,t){return new Promise(function(e,r){null!==l&&t.lengthf?r(i+" cannot be longer than "+f):e()})})}}),r}},{key:"validate",value:function(e){var t=this,r=this.getValidationsDescriptors(e);if(Object.keys(r).length){var n=new a.default(r),i=new FormData(this.userForm.dom),s={};return i.forEach(function(e,t){s[t]=e}),this.step.querySelectorAll('input[type="radio"],input[type="checkbox"]').forEach(function(e){var t=e.getAttribute("name");void 0===s[t]&&(s[t]="")}),new Promise(function(e,r){n.validate(s,function(n){n&&n.length?(t.displayErrorMessages(n),r(n)):(t.displayErrorMessages([]),e())})})}return new Promise(function(e){e()})}},{key:"enableLiveValidation",value:function(){var e=this;this.step.querySelectorAll("input, textarea, select").forEach(function(t){t.addEventListener("change",function(){t.classList.add("dirty")}),t.addEventListener("focusout",function(){e.validate(!0).then(function(){}).catch(function(){})})})}},{key:"displayErrorMessages",value:function(e){var t=this,r=[];e.forEach(function(e){var n=t.userForm.dom.querySelector("#"+e.field);if(n){var i=n.querySelector("span.error");i||(i=document.createElement("span"),i.classList.add("error"),i.setAttribute("data-id",e.field)),r.push(e.field),i.innerHTML=e.message,n.append(i)}}),this.step.querySelectorAll("span.error").forEach(function(e){var t=e.getAttribute("data-id");-1===r.indexOf(t)&&e.remove()})}}]),e}(),p=function(){function e(t,r){i(this,e),this.dom=t,this.userForm=r,this.prevButton=t.querySelector(".step-button-prev"),this.nextButton=t.querySelector(".step-button-next"),this.init()}return u(e,[{key:"init",value:function(){var e=this;this.prevButton.addEventListener("click",function(t){t.preventDefault(),window.triggerDispatchEvent(e.userForm.dom,"userform.action.prev")}),this.nextButton.addEventListener("click",function(t){t.preventDefault(),window.triggerDispatchEvent(e.userForm.dom,"userform.action.next")}),this.update(),this.userForm.dom.addEventListener("userform.form.changestep",function(){e.update()}),this.userForm.dom.addEventListener("userform.form.conditionalstep",function(){e.update()})}},{key:"update",value:function(){var e=this.userForm.getNumberOfSteps(),t=this.userForm.getCurrentStepID(),r=null,n=null;for(r=e-1;r>=0;r--)if(n=this.userForm.getStep(r),!n.conditionallyHidden()){t>=r?this.nextButton.parentNode.classList.add("hide"):this.nextButton.parentNode.classList.remove("hide"),t>0&&t<=r?this.prevButton.parentNode.classList.remove("hide"):this.prevButton.parentNode.classList.add("hide"),t>=r?this.dom.querySelector(".btn-toolbar").classList.remove("hide"):this.dom.querySelector(".btn-toolbar").classList.add("hide");break}}}]),e}(),h=function(){function e(t){i(this,e),this.dom=t,this.CONSTANTS={},this.steps=[],this.progressBar=null,this.actions=null,this.currentStep=null,this.CONSTANTS.ENABLE_LIVE_VALIDATION=void 0!==this.dom.getAttribute("livevalidation"),this.CONSTANTS.DISPLAY_ERROR_MESSAGES_AT_TOP=void 0!==this.dom.getAttribute("toperrors"),this.CONSTANTS.ENABLE_ARE_YOU_SURE=void 0!==this.dom.getAttribute("enableareyousure")}return u(e,[{key:"init",value:function(){this.initialiseFormSteps(),this.CONSTANTS.ENABLE_ARE_YOU_SURE&&this.initAreYouSure()}},{key:"initialiseFormSteps",value:function(){var e=this;this.dom.querySelectorAll(".form-step").forEach(function(t){var r=new d(t,e);r.hide(),e.addStep(r),e.CONSTANTS.ENABLE_LIVE_VALIDATION&&r.enableLiveValidation()}),this.setCurrentStep(this.steps[0]);var t=this.dom.querySelector(".userform-progress");t&&(this.progressBar=new c(t,this));var r=this.dom.querySelector(".step-navigation");r&&(this.formActions=new p(r,this),this.formActions.update()),this.setUpPing(),this.dom.addEventListener("userform.action.next",function(){e.nextStep()}),this.dom.addEventListener("userform.action.prev",function(){e.prevStep()}),this.dom.addEventListener("submit",function(t){e.validateForm(t)})}},{key:"validateForm",value:function(e){var t=this;e.preventDefault(),this.currentStep.validate().then(function(e){e||t.dom.submit()}).catch(function(){})}},{key:"setCurrentStep",value:function(e){e instanceof d&&(this.currentStep=e,this.currentStep.show())}},{key:"addStep",value:function(e){e instanceof d&&(e.setId(this.steps.length),this.steps.push(e))}},{key:"getNumberOfSteps",value:function(){return this.steps.length}},{key:"getCurrentStepID",value:function(){return this.currentStep.id?this.currentStep.id:0}},{key:"getStep",value:function(e){return this.steps[e]}},{key:"nextStep",value:function(){var e=this;this.currentStep.validate().then(function(){e.jumpToStep(e.steps.indexOf(e.currentStep)+1,!0)}).catch(function(){})}},{key:"prevStep",value:function(){this.jumpToStep(this.steps.indexOf(this.currentStep)-1,!0)}},{key:"jumpToStep",value:function(e,t){var r=this.steps[e],n=void 0===t||t;if(void 0!==r){if(r.conditionallyHidden())return void(n?this.jumpToStep(e+1,t):this.jumpToStep(e-1,t));this.currentStep&&this.currentStep.hide(),this.setCurrentStep(r),window.triggerDispatchEvent(this.dom,"userform.form.changestep",{stepId:r.id})}}},{key:"setUpPing",value:function(){window.setInterval(function(){fetch("UserDefinedFormController/ping")},18e4)}},{key:"initAreYouSure",value:function(){var e=this;window.addEventListener("beforeunload",function(t){if(0===e.dom.querySelectorAll(".dirty").length)return!0;if(navigator.userAgent.toLowerCase().match(/msie|chrome/)){if(window.hasUserFormsPropted)return;window.hasUserFormsPropted=!0,window.setTimeout(function(){window.hasUserFormsPropted=!1},900)}t.preventDefault(),event.returnValue=f.default._t("UserForms.LEAVE_CONFIRMATION","You have unsaved changes!")})}}]),e}();document.addEventListener("DOMContentLoaded",function(){document.querySelectorAll("form.userform").forEach(function(e){new h(e).init()})})},"./client/src/bundles/bundle.js":function(e,t,r){"use strict";r("./client/src/bundles/UserForms.js")},"./node_modules/async-validator/dist-web/index.js":function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),function(e){function n(){return n=Object.assign?Object.assign.bind():function(e){for(var t=1;t1?t-1:0),n=1;n=s)return e;switch(e){case"%s":return String(r[i++]);case"%d":return Number(r[i++]);case"%j":try{return JSON.stringify(r[i++])}catch(e){return"[Circular]"}break;default:return e}}):e}function p(e){return"string"===e||"url"===e||"hex"===e||"email"===e||"date"===e||"pattern"===e}function h(e,t){return void 0===e||null===e||!("array"!==t||!Array.isArray(e)||e.length)||!(!p(t)||"string"!=typeof e||e)}function m(e,t,r){function n(e){i.push.apply(i,e||[]),++s===u&&r(i)}var i=[],s=0,u=e.length;e.forEach(function(e){t(e,n)})}function v(e,t,r){function n(u){if(u&&u.length)return void r(u);var o=i;i+=1,o()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+\.)+[a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]{2,}))$/,hex:/^#?([a-f0-9]{6}|[a-f0-9]{3})$/i},P={integer:function(e){return P.number(e)&&parseInt(e,10)===e},float:function(e){return P.number(e)&&!P.integer(e)},array:function(e){return Array.isArray(e)},regexp:function(e){if(e instanceof RegExp)return!0;try{return!!new RegExp(e)}catch(e){return!1}},date:function(e){return"function"==typeof e.getTime&&"function"==typeof e.getMonth&&"function"==typeof e.getYear&&!isNaN(e.getTime())},number:function(e){return!isNaN(e)&&"number"==typeof e},object:function(e){return"object"==typeof e&&!P.array(e)},method:function(e){return"function"==typeof e},email:function(e){return"string"==typeof e&&e.length<=320&&!!e.match(k.email)},url:function(e){return"string"==typeof e&&e.length<=2048&&!!e.match(j())},hex:function(e){return"string"==typeof e&&!!e.match(k.hex)}},_=function(e,t,r,n,i){if(e.required&&void 0===t)return void T(e,t,r,n,i);var s=["integer","float","array","regexp","object","method","email","number","date","url","hex"],u=e.type;s.indexOf(u)>-1?P[u](t)||n.push(d(i.messages.types[u],e.fullField,e.type)):u&&typeof t!==e.type&&n.push(d(i.messages.types[u],e.fullField,e.type))},N=function(e,t,r,n,i){var s="number"==typeof e.len,u="number"==typeof e.min,o="number"==typeof e.max,a=/[\uD800-\uDBFF][\uDC00-\uDFFF]/g,l=t,f=null,c="number"==typeof t,p="string"==typeof t,h=Array.isArray(t);if(c?f="number":p?f="string":h&&(f="array"),!f)return!1;h&&(l=t.length),p&&(l=t.replace(a,"_").length),s?l!==e.len&&n.push(d(i.messages[f].len,e.fullField,e.len)):u&&!o&&le.max?n.push(d(i.messages[f].max,e.fullField,e.max)):u&&o&&(le.max)&&n.push(d(i.messages[f].range,e.fullField,e.min,e.max))},D=function(e,t,r,n,i){e.enum=Array.isArray(e.enum)?e.enum:[],-1===e.enum.indexOf(t)&&n.push(d(i.messages.enum,e.fullField,e.enum.join(", ")))},R=function(e,t,r,n,i){if(e.pattern)if(e.pattern instanceof RegExp)e.pattern.lastIndex=0,e.pattern.test(t)||n.push(d(i.messages.pattern.mismatch,e.fullField,t,e.pattern));else if("string"==typeof e.pattern){var s=new RegExp(e.pattern);s.test(t)||n.push(d(i.messages.pattern.mismatch,e.fullField,t,e.pattern))}},V={required:T,whitespace:L,type:_,range:N,enum:D,pattern:R},C=function(e,t,r,n,i){var s=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(h(t,"string")&&!e.required)return r();V.required(e,t,n,s,i,"string"),h(t,"string")||(V.type(e,t,n,s,i),V.range(e,t,n,s,i),V.pattern(e,t,n,s,i),!0===e.whitespace&&V.whitespace(e,t,n,s,i))}r(s)},I=function(e,t,r,n,i){var s=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(h(t)&&!e.required)return r();V.required(e,t,n,s,i),void 0!==t&&V.type(e,t,n,s,i)}r(s)},M=function(e,t,r,n,i){var s=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(""===t&&(t=void 0),h(t)&&!e.required)return r();V.required(e,t,n,s,i),void 0!==t&&(V.type(e,t,n,s,i),V.range(e,t,n,s,i))}r(s)},B=function(e,t,r,n,i){var s=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(h(t)&&!e.required)return r();V.required(e,t,n,s,i),void 0!==t&&V.type(e,t,n,s,i)}r(s)},U=function(e,t,r,n,i){var s=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(h(t)&&!e.required)return r();V.required(e,t,n,s,i),h(t)||V.type(e,t,n,s,i)}r(s)},H=function(e,t,r,n,i){var s=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(h(t)&&!e.required)return r();V.required(e,t,n,s,i),void 0!==t&&(V.type(e,t,n,s,i),V.range(e,t,n,s,i))}r(s)},$=function(e,t,r,n,i){var s=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(h(t)&&!e.required)return r();V.required(e,t,n,s,i),void 0!==t&&(V.type(e,t,n,s,i),V.range(e,t,n,s,i))}r(s)},z=function(e,t,r,n,i){var s=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if((void 0===t||null===t)&&!e.required)return r();V.required(e,t,n,s,i,"array"),void 0!==t&&null!==t&&(V.type(e,t,n,s,i),V.range(e,t,n,s,i))}r(s)},Y=function(e,t,r,n,i){var s=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(h(t)&&!e.required)return r();V.required(e,t,n,s,i),void 0!==t&&V.type(e,t,n,s,i)}r(s)},J=function(e,t,r,n,i){var s=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(h(t)&&!e.required)return r();V.required(e,t,n,s,i),void 0!==t&&V.enum(e,t,n,s,i)}r(s)},Z=function(e,t,r,n,i){var s=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(h(t,"string")&&!e.required)return r();V.required(e,t,n,s,i),h(t,"string")||V.pattern(e,t,n,s,i)}r(s)},G=function(e,t,r,n,i){var s=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(h(t,"date")&&!e.required)return r();if(V.required(e,t,n,s,i),!h(t,"date")){var u;u=t instanceof Date?t:new Date(t),V.type(e,u,n,s,i),u&&V.range(e,u.getTime(),n,s,i)}}r(s)},W=function(e,t,r,n,i){var s=[],u=Array.isArray(t)?"array":typeof t;V.required(e,t,n,s,i,u),r(s)},K=function(e,t,r,n,i){var s=e.type,u=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(h(t,s)&&!e.required)return r();V.required(e,t,n,u,i,s),h(t,s)||V.type(e,t,n,u,i)}r(u)},Q=function(e,t,r,n,i){var s=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(h(t)&&!e.required)return r();V.required(e,t,n,s,i)}r(s)},X={string:C,method:I,number:M,boolean:B,regexp:U,integer:H,float:$,array:z,object:Y,enum:J,pattern:Z,date:G,url:K,hex:K,email:K,required:W,any:Q},ee=A(),te=function(){function e(e){this.rules=null,this._messages=ee,this.define(e)}var t=e.prototype;return t.define=function(e){var t=this;if(!e)throw new Error("Cannot configure a schema with no rules");if("object"!=typeof e||Array.isArray(e))throw new Error("Rules must be an object");this.rules={},Object.keys(e).forEach(function(r){var n=e[r];t.rules[r]=Array.isArray(n)?n:[n]})},t.messages=function(e){return e&&(this._messages=q(A(),e)),this._messages},t.validate=function(t,r,i){function s(e){for(var t=[],r={},n=0;n1)for(var r=1;ra?r(i+" cannot be greater than "+a):e()})});var l=n.getAttribute("data-rule-minlength"),c=n.getAttribute("data-rule-maxlength");null===l&&null===c||(r[n.getAttribute("name")].asyncValidator=function(e,t){return new Promise(function(e,r){null!==l&&t.lengthc?r(i+" cannot be longer than "+c):e()})})}}),r}},{key:"validate",value:function(e){var t=this,r=this.getValidationsDescriptors(e);if(Object.keys(r).length){var n=new a.default(r),i=new FormData(this.userForm.dom),s={};return i.forEach(function(e,t){s[t]=e}),this.step.querySelectorAll('input[type="radio"],input[type="checkbox"]').forEach(function(e){var t=e.getAttribute("name");void 0===s[t]&&(s[t]="")}),new Promise(function(e,r){n.validate(s,function(n){n&&n.length?(t.displayErrorMessages(n),r(n)):(t.displayErrorMessages([]),e())})})}return new Promise(function(e){e()})}},{key:"enableLiveValidation",value:function(){var e=this;this.step.querySelectorAll("input, textarea, select").forEach(function(t){t.addEventListener("focusin",function(){t.classList.add("focused")}),t.addEventListener("change",function(){t.classList.add("dirty")}),t.addEventListener("focusout",function(){e.validate(!0).then(function(){}).catch(function(){})})})}},{key:"displayErrorMessages",value:function(e){var t=this,r=[];e.forEach(function(e){var n=t.userForm.dom.querySelector("#"+e.field);if(n){var i=n.querySelector("span.error");i||(i=document.createElement("span"),i.classList.add("error"),i.setAttribute("data-id",e.field)),r.push(e.field),i.innerHTML=e.message,n.append(i)}}),this.step.querySelectorAll("span.error").forEach(function(e){var t=e.getAttribute("data-id");-1===r.indexOf(t)&&e.remove()})}}]),e}(),p=function(){function e(t,r){i(this,e),this.dom=t,this.userForm=r,this.prevButton=t.querySelector(".step-button-prev"),this.nextButton=t.querySelector(".step-button-next"),this.init()}return u(e,[{key:"init",value:function(){var e=this;this.prevButton.addEventListener("click",function(t){t.preventDefault(),window.triggerDispatchEvent(e.userForm.dom,"userform.action.prev")}),this.nextButton.addEventListener("click",function(t){t.preventDefault(),window.triggerDispatchEvent(e.userForm.dom,"userform.action.next")}),this.update(),this.userForm.dom.addEventListener("userform.form.changestep",function(){e.update()}),this.userForm.dom.addEventListener("userform.form.conditionalstep",function(){e.update()})}},{key:"update",value:function(){var e=this.userForm.getNumberOfSteps(),t=this.userForm.getCurrentStepID(),r=null,n=null;for(r=e-1;r>=0;r--)if(n=this.userForm.getStep(r),!n.conditionallyHidden()){t>=r?this.nextButton.parentNode.classList.add("hide"):this.nextButton.parentNode.classList.remove("hide"),t>0&&t<=r?this.prevButton.parentNode.classList.remove("hide"):this.prevButton.parentNode.classList.add("hide"),t>=r?this.dom.querySelector(".btn-toolbar").classList.remove("hide"):this.dom.querySelector(".btn-toolbar").classList.add("hide");break}}}]),e}(),h=function(){function e(t){i(this,e),this.dom=t,this.CONSTANTS={},this.steps=[],this.progressBar=null,this.actions=null,this.currentStep=null,this.CONSTANTS.ENABLE_LIVE_VALIDATION=void 0!==this.dom.getAttribute("livevalidation"),this.CONSTANTS.DISPLAY_ERROR_MESSAGES_AT_TOP=void 0!==this.dom.getAttribute("toperrors"),this.CONSTANTS.ENABLE_ARE_YOU_SURE=void 0!==this.dom.getAttribute("enableareyousure")}return u(e,[{key:"init",value:function(){this.initialiseFormSteps(),this.CONSTANTS.ENABLE_ARE_YOU_SURE&&this.initAreYouSure()}},{key:"initialiseFormSteps",value:function(){var e=this;this.dom.querySelectorAll(".form-step").forEach(function(t){var r=new d(t,e);r.hide(),e.addStep(r),e.CONSTANTS.ENABLE_LIVE_VALIDATION&&r.enableLiveValidation()}),this.setCurrentStep(this.steps[0]);var t=this.dom.querySelector(".userform-progress");t&&(this.progressBar=new f(t,this));var r=this.dom.querySelector(".step-navigation");r&&(this.formActions=new p(r,this),this.formActions.update()),this.setUpPing(),this.dom.addEventListener("userform.action.next",function(){e.nextStep()}),this.dom.addEventListener("userform.action.prev",function(){e.prevStep()}),this.dom.addEventListener("submit",function(t){e.validateForm(t)})}},{key:"validateForm",value:function(e){var t=this;e.preventDefault(),this.currentStep.validate().then(function(e){e||t.dom.submit()}).catch(function(){})}},{key:"setCurrentStep",value:function(e){e instanceof d&&(this.currentStep=e,this.currentStep.show())}},{key:"addStep",value:function(e){e instanceof d&&(e.setId(this.steps.length),this.steps.push(e))}},{key:"getNumberOfSteps",value:function(){return this.steps.length}},{key:"getCurrentStepID",value:function(){return this.currentStep.id?this.currentStep.id:0}},{key:"getStep",value:function(e){return this.steps[e]}},{key:"nextStep",value:function(){var e=this;this.currentStep.validate().then(function(){e.jumpToStep(e.steps.indexOf(e.currentStep)+1,!0)}).catch(function(){})}},{key:"prevStep",value:function(){this.jumpToStep(this.steps.indexOf(this.currentStep)-1,!0)}},{key:"jumpToStep",value:function(e,t){var r=this.steps[e],n=void 0===t||t;if(void 0!==r){if(r.conditionallyHidden())return void(n?this.jumpToStep(e+1,t):this.jumpToStep(e-1,t));this.currentStep&&this.currentStep.hide(),this.setCurrentStep(r),window.triggerDispatchEvent(this.dom,"userform.form.changestep",{stepId:r.id})}}},{key:"setUpPing",value:function(){window.setInterval(function(){fetch("UserDefinedFormController/ping")},18e4)}},{key:"initAreYouSure",value:function(){var e=this;window.addEventListener("beforeunload",function(t){if(0===e.dom.querySelectorAll(".dirty").length)return!0;if(navigator.userAgent.toLowerCase().match(/msie|chrome/)){if(window.hasUserFormsPropted)return;window.hasUserFormsPropted=!0,window.setTimeout(function(){window.hasUserFormsPropted=!1},900)}t.preventDefault(),event.returnValue=c.default._t("UserForms.LEAVE_CONFIRMATION","You have unsaved changes!")})}}]),e}();document.addEventListener("DOMContentLoaded",function(){document.querySelectorAll("form.userform").forEach(function(e){new h(e).init()})})},"./client/src/bundles/bundle.js":function(e,t,r){"use strict";r("./client/src/bundles/UserForms.js")},"./node_modules/async-validator/dist-web/index.js":function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),function(e){function n(){return n=Object.assign?Object.assign.bind():function(e){for(var t=1;t1?t-1:0),n=1;n=s)return e;switch(e){case"%s":return String(r[i++]);case"%d":return Number(r[i++]);case"%j":try{return JSON.stringify(r[i++])}catch(e){return"[Circular]"}break;default:return e}}):e}function p(e){return"string"===e||"url"===e||"hex"===e||"email"===e||"date"===e||"pattern"===e}function h(e,t){return void 0===e||null===e||!("array"!==t||!Array.isArray(e)||e.length)||!(!p(t)||"string"!=typeof e||e)}function m(e,t,r){function n(e){i.push.apply(i,e||[]),++s===u&&r(i)}var i=[],s=0,u=e.length;e.forEach(function(e){t(e,n)})}function v(e,t,r){function n(u){if(u&&u.length)return void r(u);var o=i;i+=1,o()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+\.)+[a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]{2,}))$/,hex:/^#?([a-f0-9]{6}|[a-f0-9]{3})$/i},P={integer:function(e){return P.number(e)&&parseInt(e,10)===e},float:function(e){return P.number(e)&&!P.integer(e)},array:function(e){return Array.isArray(e)},regexp:function(e){if(e instanceof RegExp)return!0;try{return!!new RegExp(e)}catch(e){return!1}},date:function(e){return"function"==typeof e.getTime&&"function"==typeof e.getMonth&&"function"==typeof e.getYear&&!isNaN(e.getTime())},number:function(e){return!isNaN(e)&&"number"==typeof e},object:function(e){return"object"==typeof e&&!P.array(e)},method:function(e){return"function"==typeof e},email:function(e){return"string"==typeof e&&e.length<=320&&!!e.match(k.email)},url:function(e){return"string"==typeof e&&e.length<=2048&&!!e.match(j())},hex:function(e){return"string"==typeof e&&!!e.match(k.hex)}},_=function(e,t,r,n,i){if(e.required&&void 0===t)return void L(e,t,r,n,i);var s=["integer","float","array","regexp","object","method","email","number","date","url","hex"],u=e.type;s.indexOf(u)>-1?P[u](t)||n.push(d(i.messages.types[u],e.fullField,e.type)):u&&typeof t!==e.type&&n.push(d(i.messages.types[u],e.fullField,e.type))},N=function(e,t,r,n,i){var s="number"==typeof e.len,u="number"==typeof e.min,o="number"==typeof e.max,a=/[\uD800-\uDBFF][\uDC00-\uDFFF]/g,l=t,c=null,f="number"==typeof t,p="string"==typeof t,h=Array.isArray(t);if(f?c="number":p?c="string":h&&(c="array"),!c)return!1;h&&(l=t.length),p&&(l=t.replace(a,"_").length),s?l!==e.len&&n.push(d(i.messages[c].len,e.fullField,e.len)):u&&!o&&le.max?n.push(d(i.messages[c].max,e.fullField,e.max)):u&&o&&(le.max)&&n.push(d(i.messages[c].range,e.fullField,e.min,e.max))},D=function(e,t,r,n,i){e.enum=Array.isArray(e.enum)?e.enum:[],-1===e.enum.indexOf(t)&&n.push(d(i.messages.enum,e.fullField,e.enum.join(", ")))},R=function(e,t,r,n,i){if(e.pattern)if(e.pattern instanceof RegExp)e.pattern.lastIndex=0,e.pattern.test(t)||n.push(d(i.messages.pattern.mismatch,e.fullField,t,e.pattern));else if("string"==typeof e.pattern){var s=new RegExp(e.pattern);s.test(t)||n.push(d(i.messages.pattern.mismatch,e.fullField,t,e.pattern))}},V={required:L,whitespace:T,type:_,range:N,enum:D,pattern:R},C=function(e,t,r,n,i){var s=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(h(t,"string")&&!e.required)return r();V.required(e,t,n,s,i,"string"),h(t,"string")||(V.type(e,t,n,s,i),V.range(e,t,n,s,i),V.pattern(e,t,n,s,i),!0===e.whitespace&&V.whitespace(e,t,n,s,i))}r(s)},I=function(e,t,r,n,i){var s=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(h(t)&&!e.required)return r();V.required(e,t,n,s,i),void 0!==t&&V.type(e,t,n,s,i)}r(s)},M=function(e,t,r,n,i){var s=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(""===t&&(t=void 0),h(t)&&!e.required)return r();V.required(e,t,n,s,i),void 0!==t&&(V.type(e,t,n,s,i),V.range(e,t,n,s,i))}r(s)},B=function(e,t,r,n,i){var s=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(h(t)&&!e.required)return r();V.required(e,t,n,s,i),void 0!==t&&V.type(e,t,n,s,i)}r(s)},U=function(e,t,r,n,i){var s=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(h(t)&&!e.required)return r();V.required(e,t,n,s,i),h(t)||V.type(e,t,n,s,i)}r(s)},H=function(e,t,r,n,i){var s=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(h(t)&&!e.required)return r();V.required(e,t,n,s,i),void 0!==t&&(V.type(e,t,n,s,i),V.range(e,t,n,s,i))}r(s)},$=function(e,t,r,n,i){var s=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(h(t)&&!e.required)return r();V.required(e,t,n,s,i),void 0!==t&&(V.type(e,t,n,s,i),V.range(e,t,n,s,i))}r(s)},z=function(e,t,r,n,i){var s=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if((void 0===t||null===t)&&!e.required)return r();V.required(e,t,n,s,i,"array"),void 0!==t&&null!==t&&(V.type(e,t,n,s,i),V.range(e,t,n,s,i))}r(s)},Y=function(e,t,r,n,i){var s=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(h(t)&&!e.required)return r();V.required(e,t,n,s,i),void 0!==t&&V.type(e,t,n,s,i)}r(s)},J=function(e,t,r,n,i){var s=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(h(t)&&!e.required)return r();V.required(e,t,n,s,i),void 0!==t&&V.enum(e,t,n,s,i)}r(s)},Z=function(e,t,r,n,i){var s=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(h(t,"string")&&!e.required)return r();V.required(e,t,n,s,i),h(t,"string")||V.pattern(e,t,n,s,i)}r(s)},G=function(e,t,r,n,i){var s=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(h(t,"date")&&!e.required)return r();if(V.required(e,t,n,s,i),!h(t,"date")){var u;u=t instanceof Date?t:new Date(t),V.type(e,u,n,s,i),u&&V.range(e,u.getTime(),n,s,i)}}r(s)},W=function(e,t,r,n,i){var s=[],u=Array.isArray(t)?"array":typeof t;V.required(e,t,n,s,i,u),r(s)},K=function(e,t,r,n,i){var s=e.type,u=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(h(t,s)&&!e.required)return r();V.required(e,t,n,u,i,s),h(t,s)||V.type(e,t,n,u,i)}r(u)},Q=function(e,t,r,n,i){var s=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(h(t)&&!e.required)return r();V.required(e,t,n,s,i)}r(s)},X={string:C,method:I,number:M,boolean:B,regexp:U,integer:H,float:$,array:z,object:Y,enum:J,pattern:Z,date:G,url:K,hex:K,email:K,required:W,any:Q},ee=A(),te=function(){function e(e){this.rules=null,this._messages=ee,this.define(e)}var t=e.prototype;return t.define=function(e){var t=this;if(!e)throw new Error("Cannot configure a schema with no rules");if("object"!=typeof e||Array.isArray(e))throw new Error("Rules must be an object");this.rules={},Object.keys(e).forEach(function(r){var n=e[r];t.rules[r]=Array.isArray(n)?n:[n]})},t.messages=function(e){return e&&(this._messages=q(A(),e)),this._messages},t.validate=function(t,r,i){function s(e){for(var t=[],r={},n=0;n1)for(var r=1;r {\n button.addEventListener('click', (e) => {\n e.preventDefault();\n const stepNumber = parseInt(button.getAttribute('data-step'), 10);\n this.userForm.jumpToStep(stepNumber - 1);\n return false;\n });\n });\n this.userForm.dom.addEventListener('userform.form.changestep', (e) => {\n this.update(e.detail.stepId);\n });\n this.update(0);\n }\n\n update(stepId) {\n const stepNumber = this.userForm.getCurrentStepID() + 1;\n const newStep = this.userForm.getStep(stepId);\n const newStepElement = newStep.step;\n let barWidth = (stepId / (this.buttons.length - 1)) * 100;\n\n this.currentStepNumber.innerText = stepNumber;\n\n this.dom.querySelectorAll('[aria-valuenow]').forEach((e) => {\n e.setAttribute('aria-valuenow', stepNumber);\n });\n\n this.buttons.forEach((button) => {\n const btn = button;\n const parent = btn.parentNode;\n if (parseInt(btn.getAttribute('data-step'), 10) === stepNumber\n && isVisible(btn)) {\n parent.classList.add('current');\n parent.classList.add('viewed');\n\n btn.disabled = false;\n }\n parent.classList.remove('current');\n });\n\n this.progressTitle.innerText = newStepElement.getAttribute('data-title');\n\n // Update the width of the progress bar.\n barWidth = barWidth ? `${barWidth}%` : '';\n this.dom.querySelector('.progress-bar').style.width = barWidth;\n }\n}\n\nclass FormStep {\n constructor(step, userForm) {\n this.step = step;\n this.userForm = userForm;\n this.viewed = false;\n this.buttonHolder = null;\n this.id = 0;\n\n this.init();\n }\n\n init() {\n const id = this.getHTMLId();\n this.buttonHolder = document.querySelector(`.step-button-wrapper[data-for='${id}']`);\n ['userform.field.hide', 'userform.field.show'].forEach((action) => {\n this.buttonHolder.addEventListener(action, () => {\n this.userForm.dom.trigger('userform.form.conditionalstep');\n });\n });\n }\n\n setId(id) {\n this.id = id;\n }\n\n getHTMLId() {\n return this.step.getAttribute('id');\n }\n\n show() {\n this.step.setAttribute('aria-hidden', false);\n this.step.classList.remove('hide');\n this.step.classList.add('viewed');\n this.viewed = true;\n }\n\n hide() {\n this.step.setAttribute('aria-hidden', true);\n this.step.classList.add('hide');\n }\n\n conditionallyHidden() {\n const button = this.buttonHolder.querySelector('button');\n return !(button.style.display !== 'none' && button.visibility !== 'hidden' && !button.classList.contains('hide'));\n }\n\n\n getValidatorType(input) {\n if (input.getAttribute('type') === 'email') {\n return 'email';\n }\n if (input.getAttribute('type') === 'date') {\n return 'date';\n }\n if (input.classList.contains('numeric') || input.getAttribute('type') === 'numeric') {\n return 'number';\n }\n return 'string';\n }\n\n getValidatorMessage(input) {\n if (input.getAttribute('data-msg-required')) {\n return input.getAttribute('data-msg-required');\n }\n return `${this.getFieldLabel(input)} is required`;\n }\n\n getHolderForField(input) {\n return window.closest(input, '.field');\n }\n\n getFieldLabel(input) {\n const holder = this.getHolderForField(input);\n if (holder) {\n const label = holder.querySelector('label.left, legend.left');\n if (label) {\n return label.innerText;\n }\n }\n return input.getAttribute('name');\n }\n\n getValidationsDescriptors(onlyDirty) {\n const descriptors = {};\n const fields = this.step.querySelectorAll('input, textarea, select');\n\n fields.forEach((field) => {\n if (isVisible(field) && (!onlyDirty || (onlyDirty && !field.classList.contains('dirty')))) {\n const label = this.getFieldLabel(field);\n const holder = this.getHolderForField(field);\n\n descriptors[field.getAttribute('name')] = {\n title: label,\n type: this.getValidatorType(field),\n required: holder.classList.contains('requiredField'),\n message: this.getValidatorMessage(field)\n };\n\n const min = field.getAttribute('data-rule-min');\n const max = field.getAttribute('data-rule-max');\n if (min !== null || max !== null) {\n descriptors[field.getAttribute('name')].asyncValidator = function numericValidator(rule, value) {\n return new Promise((resolve, reject) => {\n if (min !== null && value < min) {\n reject(`${label} cannot be less than ${min}`);\n } else if (max !== null && value > max) {\n reject(`${label} cannot be greater than ${max}`);\n } else {\n resolve();\n }\n });\n };\n }\n\n const minL = field.getAttribute('data-rule-minlength');\n const maxL = field.getAttribute('data-rule-maxlength');\n if (minL !== null || maxL !== null) {\n descriptors[field.getAttribute('name')].asyncValidator = function lengthValidator(rule, value) {\n return new Promise((resolve, reject) => {\n if (minL !== null && value.length < minL) {\n reject(`${label} cannot be shorter than ${minL}`);\n } else if (maxL !== null && value.length > maxL) {\n reject(`${label} cannot be longer than ${maxL}`);\n } else {\n resolve();\n }\n });\n };\n }\n }\n });\n\n return descriptors;\n }\n\n validate(onlyDirty) {\n const descriptors = this.getValidationsDescriptors(onlyDirty);\n if (Object.keys(descriptors).length) {\n const validator = new Schema(descriptors);\n\n const formData = new FormData(this.userForm.dom);\n const data = {};\n formData.forEach((value, key) => {\n data[key] = value;\n });\n\n // now check for unselected checkboxes and radio buttons\n const selectableFields = this.step.querySelectorAll('input[type=\"radio\"],input[type=\"checkbox\"]');\n selectableFields.forEach((selectableField) => {\n const fieldName = selectableField.getAttribute('name');\n if (typeof data[fieldName] === 'undefined') {\n data[fieldName] = '';\n }\n });\n\n const promise = new Promise((resolve, reject) => {\n validator.validate(data, (errors) => {\n if (errors && errors.length) {\n this.displayErrorMessages(errors);\n reject(errors);\n } else {\n this.displayErrorMessages([]);\n resolve();\n }\n });\n });\n return promise;\n }\n\n const promise = new Promise((resolve) => {\n resolve();\n });\n return promise;\n }\n\n enableLiveValidation() {\n const fields = this.step.querySelectorAll('input, textarea, select');\n fields.forEach((field) => {\n field.addEventListener('change', () => {\n field.classList.add('dirty');\n });\n\n field.addEventListener('focusout', () => {\n this.validate(true).then(() => {\n }).catch(() => {\n });\n });\n });\n }\n\n displayErrorMessages(errors) {\n const errorIds = [];\n\n errors.forEach((error) => {\n const fieldHolder = this.userForm.dom.querySelector(`#${error.field}`);\n if (fieldHolder) {\n let errorLabel = fieldHolder.querySelector('span.error');\n if (!errorLabel) {\n errorLabel = document.createElement('span');\n errorLabel.classList.add('error');\n errorLabel.setAttribute('data-id', error.field);\n }\n errorIds.push(error.field);\n errorLabel.innerHTML = error.message;\n fieldHolder.append(errorLabel);\n }\n });\n\n // remove any thats not required\n const messages = this.step.querySelectorAll('span.error');\n\n messages.forEach((mesasge) => {\n const id = mesasge.getAttribute('data-id');\n if (errorIds.indexOf(id) === -1) {\n mesasge.remove();\n }\n });\n }\n}\n\nclass FormActions {\n constructor(dom, userForm) {\n this.dom = dom;\n this.userForm = userForm;\n this.prevButton = dom.querySelector('.step-button-prev');\n this.nextButton = dom.querySelector('.step-button-next');\n\n this.init();\n }\n\n init() {\n this.prevButton.addEventListener('click', (e) => {\n e.preventDefault();\n // scrollUpFx();\n window.triggerDispatchEvent(this.userForm.dom, 'userform.action.prev');\n });\n this.nextButton.addEventListener('click', (e) => {\n e.preventDefault();\n // scrollUpFx();\n window.triggerDispatchEvent(this.userForm.dom, 'userform.action.next');\n });\n\n this.update();\n\n this.userForm.dom.addEventListener('userform.form.changestep', () => {\n this.update();\n });\n\n this.userForm.dom.addEventListener('userform.form.conditionalstep', () => {\n this.update();\n });\n }\n\n update() {\n const numberOfSteps = this.userForm.getNumberOfSteps();\n const stepId = this.userForm.getCurrentStepID();\n let i = null;\n let lastStep = null;\n for (i = numberOfSteps - 1; i >= 0; i--) {\n lastStep = this.userForm.getStep(i);\n if (!lastStep.conditionallyHidden()) {\n if (stepId >= i) {\n this.nextButton.parentNode.classList.add('hide');\n } else {\n this.nextButton.parentNode.classList.remove('hide');\n }\n\n if (stepId > 0 && stepId <= i) {\n this.prevButton.parentNode.classList.remove('hide');\n } else {\n this.prevButton.parentNode.classList.add('hide');\n }\n\n if (stepId >= i) {\n this.dom.querySelector('.btn-toolbar').classList.remove('hide');\n } else {\n this.dom.querySelector('.btn-toolbar').classList.add('hide');\n }\n\n break;\n }\n }\n }\n}\n\nclass UserForm {\n constructor(form) {\n this.dom = form;\n this.CONSTANTS = {}; // Settings that come from the CMS.\n this.steps = [];\n this.progressBar = null;\n this.actions = null;\n this.currentStep = null;\n\n this.CONSTANTS.ENABLE_LIVE_VALIDATION = this.dom.getAttribute('livevalidation') !== undefined;\n this.CONSTANTS.DISPLAY_ERROR_MESSAGES_AT_TOP = this.dom.getAttribute('toperrors') !== undefined;\n this.CONSTANTS.ENABLE_ARE_YOU_SURE = this.dom.getAttribute('enableareyousure') !== undefined;\n }\n\n init() {\n this.initialiseFormSteps();\n\n if (this.CONSTANTS.ENABLE_ARE_YOU_SURE) {\n this.initAreYouSure();\n }\n }\n\n initialiseFormSteps() {\n const steps = this.dom.querySelectorAll('.form-step');\n\n steps.forEach((stepDom) => {\n const step = new FormStep(stepDom, this);\n step.hide();\n this.addStep(step);\n if (this.CONSTANTS.ENABLE_LIVE_VALIDATION) {\n step.enableLiveValidation();\n }\n });\n\n this.setCurrentStep(this.steps[0]);\n\n const progressBarDom = this.dom.querySelector('.userform-progress');\n if (progressBarDom) {\n this.progressBar = new ProgressBar(progressBarDom, this);\n }\n\n const stepNavigation = this.dom.querySelector('.step-navigation');\n if (stepNavigation) {\n this.formActions = new FormActions(stepNavigation, this);\n this.formActions.update();\n }\n\n this.setUpPing();\n\n this.dom.addEventListener('userform.action.next', () => {\n this.nextStep();\n });\n\n this.dom.addEventListener('userform.action.prev', () => {\n this.prevStep();\n });\n\n this.dom.addEventListener('submit', (e) => {\n this.validateForm(e);\n });\n }\n\n\n validateForm(e) {\n e.preventDefault();\n this.currentStep.validate()\n .then((errors) => {\n if (!errors) {\n this.dom.submit();\n }\n })\n .catch(() => {});\n }\n\n setCurrentStep(step) {\n // Make sure we're dealing with a form step.\n if (!(step instanceof FormStep)) {\n return;\n }\n this.currentStep = step;\n this.currentStep.show();\n }\n\n addStep(step) {\n if (!(step instanceof FormStep)) {\n return;\n }\n step.setId(this.steps.length);\n this.steps.push(step);\n }\n\n getNumberOfSteps() {\n return this.steps.length;\n }\n\n getCurrentStepID() {\n return this.currentStep.id ? this.currentStep.id : 0;\n }\n\n getStep(index) {\n return this.steps[index];\n }\n\n nextStep() {\n this.currentStep.validate().then(() => {\n this.jumpToStep(this.steps.indexOf(this.currentStep) + 1, true);\n }).catch(() => {});\n }\n\n prevStep() {\n this.jumpToStep(this.steps.indexOf(this.currentStep) - 1, true);\n }\n\n jumpToStep(stepNumber, direction) {\n const targetStep = this.steps[stepNumber];\n const forward = direction === undefined ? true : direction;\n\n if (targetStep === undefined) {\n return;\n }\n\n if (targetStep.conditionallyHidden()) {\n if (forward) {\n this.jumpToStep(stepNumber + 1, direction);\n } else {\n this.jumpToStep(stepNumber - 1, direction);\n }\n return;\n }\n\n if (this.currentStep) {\n this.currentStep.hide();\n }\n\n this.setCurrentStep(targetStep);\n\n window.triggerDispatchEvent(this.dom, 'userform.form.changestep', {\n stepId: targetStep.id\n });\n }\n\n setUpPing() {\n // Make sure the form doesn't expire on the user. Pings every 3 mins.\n window.setInterval(() => {\n fetch('UserDefinedFormController/ping');\n }, 180 * 1000);\n }\n\n initAreYouSure() {\n window.addEventListener('beforeunload', (e) => {\n const dirtyFields = this.dom.querySelectorAll('.dirty');\n if (dirtyFields.length === 0) {\n return true;\n }\n if (navigator.userAgent.toLowerCase().match(/msie|chrome/)) {\n if (window.hasUserFormsPropted) {\n return;\n }\n window.hasUserFormsPropted = true;\n window.setTimeout(function() {window.hasUserFormsPropted = false;}, 900);\n }\n e.preventDefault();\n event.returnValue = i18n._t('UserForms.LEAVE_CONFIRMATION', 'You have unsaved changes!');\n });\n }\n}\n\n\ndocument.addEventListener('DOMContentLoaded', () => {\n const forms = document.querySelectorAll('form.userform');\n forms.forEach((form) => {\n const userForm = new UserForm(form);\n userForm.init();\n });\n});\n\n\n\n// WEBPACK FOOTER //\n// ./client/src/bundles/UserForms.js","// Used for frontend userforms\nimport 'bundles/UserForms';\n\n\n\n// WEBPACK FOOTER //\n// ./client/src/bundles/bundle.js","function _extends() {\n _extends = Object.assign ? Object.assign.bind() : function (target) {\n for (var i = 1; i < arguments.length; i++) {\n var source = arguments[i];\n\n for (var key in source) {\n if (Object.prototype.hasOwnProperty.call(source, key)) {\n target[key] = source[key];\n }\n }\n }\n\n return target;\n };\n return _extends.apply(this, arguments);\n}\n\nfunction _inheritsLoose(subClass, superClass) {\n subClass.prototype = Object.create(superClass.prototype);\n subClass.prototype.constructor = subClass;\n\n _setPrototypeOf(subClass, superClass);\n}\n\nfunction _getPrototypeOf(o) {\n _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) {\n return o.__proto__ || Object.getPrototypeOf(o);\n };\n return _getPrototypeOf(o);\n}\n\nfunction _setPrototypeOf(o, p) {\n _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) {\n o.__proto__ = p;\n return o;\n };\n return _setPrototypeOf(o, p);\n}\n\nfunction _isNativeReflectConstruct() {\n if (typeof Reflect === \"undefined\" || !Reflect.construct) return false;\n if (Reflect.construct.sham) return false;\n if (typeof Proxy === \"function\") return true;\n\n try {\n Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));\n return true;\n } catch (e) {\n return false;\n }\n}\n\nfunction _construct(Parent, args, Class) {\n if (_isNativeReflectConstruct()) {\n _construct = Reflect.construct.bind();\n } else {\n _construct = function _construct(Parent, args, Class) {\n var a = [null];\n a.push.apply(a, args);\n var Constructor = Function.bind.apply(Parent, a);\n var instance = new Constructor();\n if (Class) _setPrototypeOf(instance, Class.prototype);\n return instance;\n };\n }\n\n return _construct.apply(null, arguments);\n}\n\nfunction _isNativeFunction(fn) {\n return Function.toString.call(fn).indexOf(\"[native code]\") !== -1;\n}\n\nfunction _wrapNativeSuper(Class) {\n var _cache = typeof Map === \"function\" ? new Map() : undefined;\n\n _wrapNativeSuper = function _wrapNativeSuper(Class) {\n if (Class === null || !_isNativeFunction(Class)) return Class;\n\n if (typeof Class !== \"function\") {\n throw new TypeError(\"Super expression must either be null or a function\");\n }\n\n if (typeof _cache !== \"undefined\") {\n if (_cache.has(Class)) return _cache.get(Class);\n\n _cache.set(Class, Wrapper);\n }\n\n function Wrapper() {\n return _construct(Class, arguments, _getPrototypeOf(this).constructor);\n }\n\n Wrapper.prototype = Object.create(Class.prototype, {\n constructor: {\n value: Wrapper,\n enumerable: false,\n writable: true,\n configurable: true\n }\n });\n return _setPrototypeOf(Wrapper, Class);\n };\n\n return _wrapNativeSuper(Class);\n}\n\n/* eslint no-console:0 */\nvar formatRegExp = /%[sdj%]/g;\nvar warning = function warning() {}; // don't print warning message when in production env or node runtime\n\nif (typeof process !== 'undefined' && process.env && process.env.NODE_ENV !== 'production' && typeof window !== 'undefined' && typeof document !== 'undefined') {\n warning = function warning(type, errors) {\n if (typeof console !== 'undefined' && console.warn && typeof ASYNC_VALIDATOR_NO_WARNING === 'undefined') {\n if (errors.every(function (e) {\n return typeof e === 'string';\n })) {\n console.warn(type, errors);\n }\n }\n };\n}\n\nfunction convertFieldsError(errors) {\n if (!errors || !errors.length) return null;\n var fields = {};\n errors.forEach(function (error) {\n var field = error.field;\n fields[field] = fields[field] || [];\n fields[field].push(error);\n });\n return fields;\n}\nfunction format(template) {\n for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n args[_key - 1] = arguments[_key];\n }\n\n var i = 0;\n var len = args.length;\n\n if (typeof template === 'function') {\n return template.apply(null, args);\n }\n\n if (typeof template === 'string') {\n var str = template.replace(formatRegExp, function (x) {\n if (x === '%%') {\n return '%';\n }\n\n if (i >= len) {\n return x;\n }\n\n switch (x) {\n case '%s':\n return String(args[i++]);\n\n case '%d':\n return Number(args[i++]);\n\n case '%j':\n try {\n return JSON.stringify(args[i++]);\n } catch (_) {\n return '[Circular]';\n }\n\n break;\n\n default:\n return x;\n }\n });\n return str;\n }\n\n return template;\n}\n\nfunction isNativeStringType(type) {\n return type === 'string' || type === 'url' || type === 'hex' || type === 'email' || type === 'date' || type === 'pattern';\n}\n\nfunction isEmptyValue(value, type) {\n if (value === undefined || value === null) {\n return true;\n }\n\n if (type === 'array' && Array.isArray(value) && !value.length) {\n return true;\n }\n\n if (isNativeStringType(type) && typeof value === 'string' && !value) {\n return true;\n }\n\n return false;\n}\n\nfunction asyncParallelArray(arr, func, callback) {\n var results = [];\n var total = 0;\n var arrLength = arr.length;\n\n function count(errors) {\n results.push.apply(results, errors || []);\n total++;\n\n if (total === arrLength) {\n callback(results);\n }\n }\n\n arr.forEach(function (a) {\n func(a, count);\n });\n}\n\nfunction asyncSerialArray(arr, func, callback) {\n var index = 0;\n var arrLength = arr.length;\n\n function next(errors) {\n if (errors && errors.length) {\n callback(errors);\n return;\n }\n\n var original = index;\n index = index + 1;\n\n if (original < arrLength) {\n func(arr[original], next);\n } else {\n callback([]);\n }\n }\n\n next([]);\n}\n\nfunction flattenObjArr(objArr) {\n var ret = [];\n Object.keys(objArr).forEach(function (k) {\n ret.push.apply(ret, objArr[k] || []);\n });\n return ret;\n}\n\nvar AsyncValidationError = /*#__PURE__*/function (_Error) {\n _inheritsLoose(AsyncValidationError, _Error);\n\n function AsyncValidationError(errors, fields) {\n var _this;\n\n _this = _Error.call(this, 'Async Validation Error') || this;\n _this.errors = errors;\n _this.fields = fields;\n return _this;\n }\n\n return AsyncValidationError;\n}( /*#__PURE__*/_wrapNativeSuper(Error));\nfunction asyncMap(objArr, option, func, callback, source) {\n if (option.first) {\n var _pending = new Promise(function (resolve, reject) {\n var next = function next(errors) {\n callback(errors);\n return errors.length ? reject(new AsyncValidationError(errors, convertFieldsError(errors))) : resolve(source);\n };\n\n var flattenArr = flattenObjArr(objArr);\n asyncSerialArray(flattenArr, func, next);\n });\n\n _pending[\"catch\"](function (e) {\n return e;\n });\n\n return _pending;\n }\n\n var firstFields = option.firstFields === true ? Object.keys(objArr) : option.firstFields || [];\n var objArrKeys = Object.keys(objArr);\n var objArrLength = objArrKeys.length;\n var total = 0;\n var results = [];\n var pending = new Promise(function (resolve, reject) {\n var next = function next(errors) {\n results.push.apply(results, errors);\n total++;\n\n if (total === objArrLength) {\n callback(results);\n return results.length ? reject(new AsyncValidationError(results, convertFieldsError(results))) : resolve(source);\n }\n };\n\n if (!objArrKeys.length) {\n callback(results);\n resolve(source);\n }\n\n objArrKeys.forEach(function (key) {\n var arr = objArr[key];\n\n if (firstFields.indexOf(key) !== -1) {\n asyncSerialArray(arr, func, next);\n } else {\n asyncParallelArray(arr, func, next);\n }\n });\n });\n pending[\"catch\"](function (e) {\n return e;\n });\n return pending;\n}\n\nfunction isErrorObj(obj) {\n return !!(obj && obj.message !== undefined);\n}\n\nfunction getValue(value, path) {\n var v = value;\n\n for (var i = 0; i < path.length; i++) {\n if (v == undefined) {\n return v;\n }\n\n v = v[path[i]];\n }\n\n return v;\n}\n\nfunction complementError(rule, source) {\n return function (oe) {\n var fieldValue;\n\n if (rule.fullFields) {\n fieldValue = getValue(source, rule.fullFields);\n } else {\n fieldValue = source[oe.field || rule.fullField];\n }\n\n if (isErrorObj(oe)) {\n oe.field = oe.field || rule.fullField;\n oe.fieldValue = fieldValue;\n return oe;\n }\n\n return {\n message: typeof oe === 'function' ? oe() : oe,\n fieldValue: fieldValue,\n field: oe.field || rule.fullField\n };\n };\n}\nfunction deepMerge(target, source) {\n if (source) {\n for (var s in source) {\n if (source.hasOwnProperty(s)) {\n var value = source[s];\n\n if (typeof value === 'object' && typeof target[s] === 'object') {\n target[s] = _extends({}, target[s], value);\n } else {\n target[s] = value;\n }\n }\n }\n }\n\n return target;\n}\n\nvar required$1 = function required(rule, value, source, errors, options, type) {\n if (rule.required && (!source.hasOwnProperty(rule.field) || isEmptyValue(value, type || rule.type))) {\n errors.push(format(options.messages.required, rule.fullField));\n }\n};\n\n/**\n * Rule for validating whitespace.\n *\n * @param rule The validation rule.\n * @param value The value of the field on the source object.\n * @param source The source object being validated.\n * @param errors An array of errors that this rule may add\n * validation errors to.\n * @param options The validation options.\n * @param options.messages The validation messages.\n */\n\nvar whitespace = function whitespace(rule, value, source, errors, options) {\n if (/^\\s+$/.test(value) || value === '') {\n errors.push(format(options.messages.whitespace, rule.fullField));\n }\n};\n\n// https://github.com/kevva/url-regex/blob/master/index.js\nvar urlReg;\nvar getUrlRegex = (function () {\n if (urlReg) {\n return urlReg;\n }\n\n var word = '[a-fA-F\\\\d:]';\n\n var b = function b(options) {\n return options && options.includeBoundaries ? \"(?:(?<=\\\\s|^)(?=\" + word + \")|(?<=\" + word + \")(?=\\\\s|$))\" : '';\n };\n\n var v4 = '(?:25[0-5]|2[0-4]\\\\d|1\\\\d\\\\d|[1-9]\\\\d|\\\\d)(?:\\\\.(?:25[0-5]|2[0-4]\\\\d|1\\\\d\\\\d|[1-9]\\\\d|\\\\d)){3}';\n var v6seg = '[a-fA-F\\\\d]{1,4}';\n var v6 = (\"\\n(?:\\n(?:\" + v6seg + \":){7}(?:\" + v6seg + \"|:)| // 1:2:3:4:5:6:7:: 1:2:3:4:5:6:7:8\\n(?:\" + v6seg + \":){6}(?:\" + v4 + \"|:\" + v6seg + \"|:)| // 1:2:3:4:5:6:: 1:2:3:4:5:6::8 1:2:3:4:5:6::8 1:2:3:4:5:6::1.2.3.4\\n(?:\" + v6seg + \":){5}(?::\" + v4 + \"|(?::\" + v6seg + \"){1,2}|:)| // 1:2:3:4:5:: 1:2:3:4:5::7:8 1:2:3:4:5::8 1:2:3:4:5::7:1.2.3.4\\n(?:\" + v6seg + \":){4}(?:(?::\" + v6seg + \"){0,1}:\" + v4 + \"|(?::\" + v6seg + \"){1,3}|:)| // 1:2:3:4:: 1:2:3:4::6:7:8 1:2:3:4::8 1:2:3:4::6:7:1.2.3.4\\n(?:\" + v6seg + \":){3}(?:(?::\" + v6seg + \"){0,2}:\" + v4 + \"|(?::\" + v6seg + \"){1,4}|:)| // 1:2:3:: 1:2:3::5:6:7:8 1:2:3::8 1:2:3::5:6:7:1.2.3.4\\n(?:\" + v6seg + \":){2}(?:(?::\" + v6seg + \"){0,3}:\" + v4 + \"|(?::\" + v6seg + \"){1,5}|:)| // 1:2:: 1:2::4:5:6:7:8 1:2::8 1:2::4:5:6:7:1.2.3.4\\n(?:\" + v6seg + \":){1}(?:(?::\" + v6seg + \"){0,4}:\" + v4 + \"|(?::\" + v6seg + \"){1,6}|:)| // 1:: 1::3:4:5:6:7:8 1::8 1::3:4:5:6:7:1.2.3.4\\n(?::(?:(?::\" + v6seg + \"){0,5}:\" + v4 + \"|(?::\" + v6seg + \"){1,7}|:)) // ::2:3:4:5:6:7:8 ::2:3:4:5:6:7:8 ::8 ::1.2.3.4\\n)(?:%[0-9a-zA-Z]{1,})? // %eth0 %1\\n\").replace(/\\s*\\/\\/.*$/gm, '').replace(/\\n/g, '').trim(); // Pre-compile only the exact regexes because adding a global flag make regexes stateful\n\n var v46Exact = new RegExp(\"(?:^\" + v4 + \"$)|(?:^\" + v6 + \"$)\");\n var v4exact = new RegExp(\"^\" + v4 + \"$\");\n var v6exact = new RegExp(\"^\" + v6 + \"$\");\n\n var ip = function ip(options) {\n return options && options.exact ? v46Exact : new RegExp(\"(?:\" + b(options) + v4 + b(options) + \")|(?:\" + b(options) + v6 + b(options) + \")\", 'g');\n };\n\n ip.v4 = function (options) {\n return options && options.exact ? v4exact : new RegExp(\"\" + b(options) + v4 + b(options), 'g');\n };\n\n ip.v6 = function (options) {\n return options && options.exact ? v6exact : new RegExp(\"\" + b(options) + v6 + b(options), 'g');\n };\n\n var protocol = \"(?:(?:[a-z]+:)?//)\";\n var auth = '(?:\\\\S+(?::\\\\S*)?@)?';\n var ipv4 = ip.v4().source;\n var ipv6 = ip.v6().source;\n var host = \"(?:(?:[a-z\\\\u00a1-\\\\uffff0-9][-_]*)*[a-z\\\\u00a1-\\\\uffff0-9]+)\";\n var domain = \"(?:\\\\.(?:[a-z\\\\u00a1-\\\\uffff0-9]-*)*[a-z\\\\u00a1-\\\\uffff0-9]+)*\";\n var tld = \"(?:\\\\.(?:[a-z\\\\u00a1-\\\\uffff]{2,}))\";\n var port = '(?::\\\\d{2,5})?';\n var path = '(?:[/?#][^\\\\s\"]*)?';\n var regex = \"(?:\" + protocol + \"|www\\\\.)\" + auth + \"(?:localhost|\" + ipv4 + \"|\" + ipv6 + \"|\" + host + domain + tld + \")\" + port + path;\n urlReg = new RegExp(\"(?:^\" + regex + \"$)\", 'i');\n return urlReg;\n});\n\n/* eslint max-len:0 */\n\nvar pattern$2 = {\n // http://emailregex.com/\n email: /^(([^<>()\\[\\]\\\\.,;:\\s@\"]+(\\.[^<>()\\[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z\\-0-9\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]+\\.)+[a-zA-Z\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]{2,}))$/,\n // url: new RegExp(\n // '^(?!mailto:)(?:(?:http|https|ftp)://|//)(?:\\\\S+(?::\\\\S*)?@)?(?:(?:(?:[1-9]\\\\d?|1\\\\d\\\\d|2[01]\\\\d|22[0-3])(?:\\\\.(?:1?\\\\d{1,2}|2[0-4]\\\\d|25[0-5])){2}(?:\\\\.(?:[0-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,})))|localhost)(?::\\\\d{2,5})?(?:(/|\\\\?|#)[^\\\\s]*)?$',\n // 'i',\n // ),\n hex: /^#?([a-f0-9]{6}|[a-f0-9]{3})$/i\n};\nvar types = {\n integer: function integer(value) {\n return types.number(value) && parseInt(value, 10) === value;\n },\n \"float\": function float(value) {\n return types.number(value) && !types.integer(value);\n },\n array: function array(value) {\n return Array.isArray(value);\n },\n regexp: function regexp(value) {\n if (value instanceof RegExp) {\n return true;\n }\n\n try {\n return !!new RegExp(value);\n } catch (e) {\n return false;\n }\n },\n date: function date(value) {\n return typeof value.getTime === 'function' && typeof value.getMonth === 'function' && typeof value.getYear === 'function' && !isNaN(value.getTime());\n },\n number: function number(value) {\n if (isNaN(value)) {\n return false;\n }\n\n return typeof value === 'number';\n },\n object: function object(value) {\n return typeof value === 'object' && !types.array(value);\n },\n method: function method(value) {\n return typeof value === 'function';\n },\n email: function email(value) {\n return typeof value === 'string' && value.length <= 320 && !!value.match(pattern$2.email);\n },\n url: function url(value) {\n return typeof value === 'string' && value.length <= 2048 && !!value.match(getUrlRegex());\n },\n hex: function hex(value) {\n return typeof value === 'string' && !!value.match(pattern$2.hex);\n }\n};\n\nvar type$1 = function type(rule, value, source, errors, options) {\n if (rule.required && value === undefined) {\n required$1(rule, value, source, errors, options);\n return;\n }\n\n var custom = ['integer', 'float', 'array', 'regexp', 'object', 'method', 'email', 'number', 'date', 'url', 'hex'];\n var ruleType = rule.type;\n\n if (custom.indexOf(ruleType) > -1) {\n if (!types[ruleType](value)) {\n errors.push(format(options.messages.types[ruleType], rule.fullField, rule.type));\n } // straight typeof check\n\n } else if (ruleType && typeof value !== rule.type) {\n errors.push(format(options.messages.types[ruleType], rule.fullField, rule.type));\n }\n};\n\nvar range = function range(rule, value, source, errors, options) {\n var len = typeof rule.len === 'number';\n var min = typeof rule.min === 'number';\n var max = typeof rule.max === 'number'; // 正则匹配码点范围从U+010000一直到U+10FFFF的文字(补充平面Supplementary Plane)\n\n var spRegexp = /[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]/g;\n var val = value;\n var key = null;\n var num = typeof value === 'number';\n var str = typeof value === 'string';\n var arr = Array.isArray(value);\n\n if (num) {\n key = 'number';\n } else if (str) {\n key = 'string';\n } else if (arr) {\n key = 'array';\n } // if the value is not of a supported type for range validation\n // the validation rule rule should use the\n // type property to also test for a particular type\n\n\n if (!key) {\n return false;\n }\n\n if (arr) {\n val = value.length;\n }\n\n if (str) {\n // 处理码点大于U+010000的文字length属性不准确的bug,如\"𠮷𠮷𠮷\".lenght !== 3\n val = value.replace(spRegexp, '_').length;\n }\n\n if (len) {\n if (val !== rule.len) {\n errors.push(format(options.messages[key].len, rule.fullField, rule.len));\n }\n } else if (min && !max && val < rule.min) {\n errors.push(format(options.messages[key].min, rule.fullField, rule.min));\n } else if (max && !min && val > rule.max) {\n errors.push(format(options.messages[key].max, rule.fullField, rule.max));\n } else if (min && max && (val < rule.min || val > rule.max)) {\n errors.push(format(options.messages[key].range, rule.fullField, rule.min, rule.max));\n }\n};\n\nvar ENUM$1 = 'enum';\n\nvar enumerable$1 = function enumerable(rule, value, source, errors, options) {\n rule[ENUM$1] = Array.isArray(rule[ENUM$1]) ? rule[ENUM$1] : [];\n\n if (rule[ENUM$1].indexOf(value) === -1) {\n errors.push(format(options.messages[ENUM$1], rule.fullField, rule[ENUM$1].join(', ')));\n }\n};\n\nvar pattern$1 = function pattern(rule, value, source, errors, options) {\n if (rule.pattern) {\n if (rule.pattern instanceof RegExp) {\n // if a RegExp instance is passed, reset `lastIndex` in case its `global`\n // flag is accidentally set to `true`, which in a validation scenario\n // is not necessary and the result might be misleading\n rule.pattern.lastIndex = 0;\n\n if (!rule.pattern.test(value)) {\n errors.push(format(options.messages.pattern.mismatch, rule.fullField, value, rule.pattern));\n }\n } else if (typeof rule.pattern === 'string') {\n var _pattern = new RegExp(rule.pattern);\n\n if (!_pattern.test(value)) {\n errors.push(format(options.messages.pattern.mismatch, rule.fullField, value, rule.pattern));\n }\n }\n }\n};\n\nvar rules = {\n required: required$1,\n whitespace: whitespace,\n type: type$1,\n range: range,\n \"enum\": enumerable$1,\n pattern: pattern$1\n};\n\nvar string = function string(rule, value, callback, source, options) {\n var errors = [];\n var validate = rule.required || !rule.required && source.hasOwnProperty(rule.field);\n\n if (validate) {\n if (isEmptyValue(value, 'string') && !rule.required) {\n return callback();\n }\n\n rules.required(rule, value, source, errors, options, 'string');\n\n if (!isEmptyValue(value, 'string')) {\n rules.type(rule, value, source, errors, options);\n rules.range(rule, value, source, errors, options);\n rules.pattern(rule, value, source, errors, options);\n\n if (rule.whitespace === true) {\n rules.whitespace(rule, value, source, errors, options);\n }\n }\n }\n\n callback(errors);\n};\n\nvar method = function method(rule, value, callback, source, options) {\n var errors = [];\n var validate = rule.required || !rule.required && source.hasOwnProperty(rule.field);\n\n if (validate) {\n if (isEmptyValue(value) && !rule.required) {\n return callback();\n }\n\n rules.required(rule, value, source, errors, options);\n\n if (value !== undefined) {\n rules.type(rule, value, source, errors, options);\n }\n }\n\n callback(errors);\n};\n\nvar number = function number(rule, value, callback, source, options) {\n var errors = [];\n var validate = rule.required || !rule.required && source.hasOwnProperty(rule.field);\n\n if (validate) {\n if (value === '') {\n value = undefined;\n }\n\n if (isEmptyValue(value) && !rule.required) {\n return callback();\n }\n\n rules.required(rule, value, source, errors, options);\n\n if (value !== undefined) {\n rules.type(rule, value, source, errors, options);\n rules.range(rule, value, source, errors, options);\n }\n }\n\n callback(errors);\n};\n\nvar _boolean = function _boolean(rule, value, callback, source, options) {\n var errors = [];\n var validate = rule.required || !rule.required && source.hasOwnProperty(rule.field);\n\n if (validate) {\n if (isEmptyValue(value) && !rule.required) {\n return callback();\n }\n\n rules.required(rule, value, source, errors, options);\n\n if (value !== undefined) {\n rules.type(rule, value, source, errors, options);\n }\n }\n\n callback(errors);\n};\n\nvar regexp = function regexp(rule, value, callback, source, options) {\n var errors = [];\n var validate = rule.required || !rule.required && source.hasOwnProperty(rule.field);\n\n if (validate) {\n if (isEmptyValue(value) && !rule.required) {\n return callback();\n }\n\n rules.required(rule, value, source, errors, options);\n\n if (!isEmptyValue(value)) {\n rules.type(rule, value, source, errors, options);\n }\n }\n\n callback(errors);\n};\n\nvar integer = function integer(rule, value, callback, source, options) {\n var errors = [];\n var validate = rule.required || !rule.required && source.hasOwnProperty(rule.field);\n\n if (validate) {\n if (isEmptyValue(value) && !rule.required) {\n return callback();\n }\n\n rules.required(rule, value, source, errors, options);\n\n if (value !== undefined) {\n rules.type(rule, value, source, errors, options);\n rules.range(rule, value, source, errors, options);\n }\n }\n\n callback(errors);\n};\n\nvar floatFn = function floatFn(rule, value, callback, source, options) {\n var errors = [];\n var validate = rule.required || !rule.required && source.hasOwnProperty(rule.field);\n\n if (validate) {\n if (isEmptyValue(value) && !rule.required) {\n return callback();\n }\n\n rules.required(rule, value, source, errors, options);\n\n if (value !== undefined) {\n rules.type(rule, value, source, errors, options);\n rules.range(rule, value, source, errors, options);\n }\n }\n\n callback(errors);\n};\n\nvar array = function array(rule, value, callback, source, options) {\n var errors = [];\n var validate = rule.required || !rule.required && source.hasOwnProperty(rule.field);\n\n if (validate) {\n if ((value === undefined || value === null) && !rule.required) {\n return callback();\n }\n\n rules.required(rule, value, source, errors, options, 'array');\n\n if (value !== undefined && value !== null) {\n rules.type(rule, value, source, errors, options);\n rules.range(rule, value, source, errors, options);\n }\n }\n\n callback(errors);\n};\n\nvar object = function object(rule, value, callback, source, options) {\n var errors = [];\n var validate = rule.required || !rule.required && source.hasOwnProperty(rule.field);\n\n if (validate) {\n if (isEmptyValue(value) && !rule.required) {\n return callback();\n }\n\n rules.required(rule, value, source, errors, options);\n\n if (value !== undefined) {\n rules.type(rule, value, source, errors, options);\n }\n }\n\n callback(errors);\n};\n\nvar ENUM = 'enum';\n\nvar enumerable = function enumerable(rule, value, callback, source, options) {\n var errors = [];\n var validate = rule.required || !rule.required && source.hasOwnProperty(rule.field);\n\n if (validate) {\n if (isEmptyValue(value) && !rule.required) {\n return callback();\n }\n\n rules.required(rule, value, source, errors, options);\n\n if (value !== undefined) {\n rules[ENUM](rule, value, source, errors, options);\n }\n }\n\n callback(errors);\n};\n\nvar pattern = function pattern(rule, value, callback, source, options) {\n var errors = [];\n var validate = rule.required || !rule.required && source.hasOwnProperty(rule.field);\n\n if (validate) {\n if (isEmptyValue(value, 'string') && !rule.required) {\n return callback();\n }\n\n rules.required(rule, value, source, errors, options);\n\n if (!isEmptyValue(value, 'string')) {\n rules.pattern(rule, value, source, errors, options);\n }\n }\n\n callback(errors);\n};\n\nvar date = function date(rule, value, callback, source, options) {\n // console.log('integer rule called %j', rule);\n var errors = [];\n var validate = rule.required || !rule.required && source.hasOwnProperty(rule.field); // console.log('validate on %s value', value);\n\n if (validate) {\n if (isEmptyValue(value, 'date') && !rule.required) {\n return callback();\n }\n\n rules.required(rule, value, source, errors, options);\n\n if (!isEmptyValue(value, 'date')) {\n var dateObject;\n\n if (value instanceof Date) {\n dateObject = value;\n } else {\n dateObject = new Date(value);\n }\n\n rules.type(rule, dateObject, source, errors, options);\n\n if (dateObject) {\n rules.range(rule, dateObject.getTime(), source, errors, options);\n }\n }\n }\n\n callback(errors);\n};\n\nvar required = function required(rule, value, callback, source, options) {\n var errors = [];\n var type = Array.isArray(value) ? 'array' : typeof value;\n rules.required(rule, value, source, errors, options, type);\n callback(errors);\n};\n\nvar type = function type(rule, value, callback, source, options) {\n var ruleType = rule.type;\n var errors = [];\n var validate = rule.required || !rule.required && source.hasOwnProperty(rule.field);\n\n if (validate) {\n if (isEmptyValue(value, ruleType) && !rule.required) {\n return callback();\n }\n\n rules.required(rule, value, source, errors, options, ruleType);\n\n if (!isEmptyValue(value, ruleType)) {\n rules.type(rule, value, source, errors, options);\n }\n }\n\n callback(errors);\n};\n\nvar any = function any(rule, value, callback, source, options) {\n var errors = [];\n var validate = rule.required || !rule.required && source.hasOwnProperty(rule.field);\n\n if (validate) {\n if (isEmptyValue(value) && !rule.required) {\n return callback();\n }\n\n rules.required(rule, value, source, errors, options);\n }\n\n callback(errors);\n};\n\nvar validators = {\n string: string,\n method: method,\n number: number,\n \"boolean\": _boolean,\n regexp: regexp,\n integer: integer,\n \"float\": floatFn,\n array: array,\n object: object,\n \"enum\": enumerable,\n pattern: pattern,\n date: date,\n url: type,\n hex: type,\n email: type,\n required: required,\n any: any\n};\n\nfunction newMessages() {\n return {\n \"default\": 'Validation error on field %s',\n required: '%s is required',\n \"enum\": '%s must be one of %s',\n whitespace: '%s cannot be empty',\n date: {\n format: '%s date %s is invalid for format %s',\n parse: '%s date could not be parsed, %s is invalid ',\n invalid: '%s date %s is invalid'\n },\n types: {\n string: '%s is not a %s',\n method: '%s is not a %s (function)',\n array: '%s is not an %s',\n object: '%s is not an %s',\n number: '%s is not a %s',\n date: '%s is not a %s',\n \"boolean\": '%s is not a %s',\n integer: '%s is not an %s',\n \"float\": '%s is not a %s',\n regexp: '%s is not a valid %s',\n email: '%s is not a valid %s',\n url: '%s is not a valid %s',\n hex: '%s is not a valid %s'\n },\n string: {\n len: '%s must be exactly %s characters',\n min: '%s must be at least %s characters',\n max: '%s cannot be longer than %s characters',\n range: '%s must be between %s and %s characters'\n },\n number: {\n len: '%s must equal %s',\n min: '%s cannot be less than %s',\n max: '%s cannot be greater than %s',\n range: '%s must be between %s and %s'\n },\n array: {\n len: '%s must be exactly %s in length',\n min: '%s cannot be less than %s in length',\n max: '%s cannot be greater than %s in length',\n range: '%s must be between %s and %s in length'\n },\n pattern: {\n mismatch: '%s value %s does not match pattern %s'\n },\n clone: function clone() {\n var cloned = JSON.parse(JSON.stringify(this));\n cloned.clone = this.clone;\n return cloned;\n }\n };\n}\nvar messages = newMessages();\n\n/**\n * Encapsulates a validation schema.\n *\n * @param descriptor An object declaring validation rules\n * for this schema.\n */\n\nvar Schema = /*#__PURE__*/function () {\n // ========================= Static =========================\n // ======================== Instance ========================\n function Schema(descriptor) {\n this.rules = null;\n this._messages = messages;\n this.define(descriptor);\n }\n\n var _proto = Schema.prototype;\n\n _proto.define = function define(rules) {\n var _this = this;\n\n if (!rules) {\n throw new Error('Cannot configure a schema with no rules');\n }\n\n if (typeof rules !== 'object' || Array.isArray(rules)) {\n throw new Error('Rules must be an object');\n }\n\n this.rules = {};\n Object.keys(rules).forEach(function (name) {\n var item = rules[name];\n _this.rules[name] = Array.isArray(item) ? item : [item];\n });\n };\n\n _proto.messages = function messages(_messages) {\n if (_messages) {\n this._messages = deepMerge(newMessages(), _messages);\n }\n\n return this._messages;\n };\n\n _proto.validate = function validate(source_, o, oc) {\n var _this2 = this;\n\n if (o === void 0) {\n o = {};\n }\n\n if (oc === void 0) {\n oc = function oc() {};\n }\n\n var source = source_;\n var options = o;\n var callback = oc;\n\n if (typeof options === 'function') {\n callback = options;\n options = {};\n }\n\n if (!this.rules || Object.keys(this.rules).length === 0) {\n if (callback) {\n callback(null, source);\n }\n\n return Promise.resolve(source);\n }\n\n function complete(results) {\n var errors = [];\n var fields = {};\n\n function add(e) {\n if (Array.isArray(e)) {\n var _errors;\n\n errors = (_errors = errors).concat.apply(_errors, e);\n } else {\n errors.push(e);\n }\n }\n\n for (var i = 0; i < results.length; i++) {\n add(results[i]);\n }\n\n if (!errors.length) {\n callback(null, source);\n } else {\n fields = convertFieldsError(errors);\n callback(errors, fields);\n }\n }\n\n if (options.messages) {\n var messages$1 = this.messages();\n\n if (messages$1 === messages) {\n messages$1 = newMessages();\n }\n\n deepMerge(messages$1, options.messages);\n options.messages = messages$1;\n } else {\n options.messages = this.messages();\n }\n\n var series = {};\n var keys = options.keys || Object.keys(this.rules);\n keys.forEach(function (z) {\n var arr = _this2.rules[z];\n var value = source[z];\n arr.forEach(function (r) {\n var rule = r;\n\n if (typeof rule.transform === 'function') {\n if (source === source_) {\n source = _extends({}, source);\n }\n\n value = source[z] = rule.transform(value);\n }\n\n if (typeof rule === 'function') {\n rule = {\n validator: rule\n };\n } else {\n rule = _extends({}, rule);\n } // Fill validator. Skip if nothing need to validate\n\n\n rule.validator = _this2.getValidationMethod(rule);\n\n if (!rule.validator) {\n return;\n }\n\n rule.field = z;\n rule.fullField = rule.fullField || z;\n rule.type = _this2.getType(rule);\n series[z] = series[z] || [];\n series[z].push({\n rule: rule,\n value: value,\n source: source,\n field: z\n });\n });\n });\n var errorFields = {};\n return asyncMap(series, options, function (data, doIt) {\n var rule = data.rule;\n var deep = (rule.type === 'object' || rule.type === 'array') && (typeof rule.fields === 'object' || typeof rule.defaultField === 'object');\n deep = deep && (rule.required || !rule.required && data.value);\n rule.field = data.field;\n\n function addFullField(key, schema) {\n return _extends({}, schema, {\n fullField: rule.fullField + \".\" + key,\n fullFields: rule.fullFields ? [].concat(rule.fullFields, [key]) : [key]\n });\n }\n\n function cb(e) {\n if (e === void 0) {\n e = [];\n }\n\n var errorList = Array.isArray(e) ? e : [e];\n\n if (!options.suppressWarning && errorList.length) {\n Schema.warning('async-validator:', errorList);\n }\n\n if (errorList.length && rule.message !== undefined) {\n errorList = [].concat(rule.message);\n } // Fill error info\n\n\n var filledErrors = errorList.map(complementError(rule, source));\n\n if (options.first && filledErrors.length) {\n errorFields[rule.field] = 1;\n return doIt(filledErrors);\n }\n\n if (!deep) {\n doIt(filledErrors);\n } else {\n // if rule is required but the target object\n // does not exist fail at the rule level and don't\n // go deeper\n if (rule.required && !data.value) {\n if (rule.message !== undefined) {\n filledErrors = [].concat(rule.message).map(complementError(rule, source));\n } else if (options.error) {\n filledErrors = [options.error(rule, format(options.messages.required, rule.field))];\n }\n\n return doIt(filledErrors);\n }\n\n var fieldsSchema = {};\n\n if (rule.defaultField) {\n Object.keys(data.value).map(function (key) {\n fieldsSchema[key] = rule.defaultField;\n });\n }\n\n fieldsSchema = _extends({}, fieldsSchema, data.rule.fields);\n var paredFieldsSchema = {};\n Object.keys(fieldsSchema).forEach(function (field) {\n var fieldSchema = fieldsSchema[field];\n var fieldSchemaList = Array.isArray(fieldSchema) ? fieldSchema : [fieldSchema];\n paredFieldsSchema[field] = fieldSchemaList.map(addFullField.bind(null, field));\n });\n var schema = new Schema(paredFieldsSchema);\n schema.messages(options.messages);\n\n if (data.rule.options) {\n data.rule.options.messages = options.messages;\n data.rule.options.error = options.error;\n }\n\n schema.validate(data.value, data.rule.options || options, function (errs) {\n var finalErrors = [];\n\n if (filledErrors && filledErrors.length) {\n finalErrors.push.apply(finalErrors, filledErrors);\n }\n\n if (errs && errs.length) {\n finalErrors.push.apply(finalErrors, errs);\n }\n\n doIt(finalErrors.length ? finalErrors : null);\n });\n }\n }\n\n var res;\n\n if (rule.asyncValidator) {\n res = rule.asyncValidator(rule, data.value, cb, data.source, options);\n } else if (rule.validator) {\n try {\n res = rule.validator(rule, data.value, cb, data.source, options);\n } catch (error) {\n console.error == null ? void 0 : console.error(error); // rethrow to report error\n\n if (!options.suppressValidatorError) {\n setTimeout(function () {\n throw error;\n }, 0);\n }\n\n cb(error.message);\n }\n\n if (res === true) {\n cb();\n } else if (res === false) {\n cb(typeof rule.message === 'function' ? rule.message(rule.fullField || rule.field) : rule.message || (rule.fullField || rule.field) + \" fails\");\n } else if (res instanceof Array) {\n cb(res);\n } else if (res instanceof Error) {\n cb(res.message);\n }\n }\n\n if (res && res.then) {\n res.then(function () {\n return cb();\n }, function (e) {\n return cb(e);\n });\n }\n }, function (results) {\n complete(results);\n }, source);\n };\n\n _proto.getType = function getType(rule) {\n if (rule.type === undefined && rule.pattern instanceof RegExp) {\n rule.type = 'pattern';\n }\n\n if (typeof rule.validator !== 'function' && rule.type && !validators.hasOwnProperty(rule.type)) {\n throw new Error(format('Unknown rule type %s', rule.type));\n }\n\n return rule.type || 'string';\n };\n\n _proto.getValidationMethod = function getValidationMethod(rule) {\n if (typeof rule.validator === 'function') {\n return rule.validator;\n }\n\n var keys = Object.keys(rule);\n var messageIndex = keys.indexOf('message');\n\n if (messageIndex !== -1) {\n keys.splice(messageIndex, 1);\n }\n\n if (keys.length === 1 && keys[0] === 'required') {\n return validators.required;\n }\n\n return validators[this.getType(rule)] || undefined;\n };\n\n return Schema;\n}();\n\nSchema.register = function register(type, validator) {\n if (typeof validator !== 'function') {\n throw new Error('Cannot register a validator by type, validator is not a function');\n }\n\n validators[type] = validator;\n};\n\nSchema.warning = warning;\nSchema.messages = messages;\nSchema.validators = validators;\n\nexport { Schema as default };\n//# sourceMappingURL=index.js.map\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/async-validator/dist-web/index.js\n// module id = ./node_modules/async-validator/dist-web/index.js\n// module chunks = 0","// shim for using process in browser\nvar process = module.exports = {};\n\n// cached from whatever global is present so that test runners that stub it\n// don't break things. But we need to wrap it in a try catch in case it is\n// wrapped in strict mode code which doesn't define any globals. It's inside a\n// function because try/catches deoptimize in certain engines.\n\nvar cachedSetTimeout;\nvar cachedClearTimeout;\n\nfunction defaultSetTimout() {\n throw new Error('setTimeout has not been defined');\n}\nfunction defaultClearTimeout () {\n throw new Error('clearTimeout has not been defined');\n}\n(function () {\n try {\n if (typeof setTimeout === 'function') {\n cachedSetTimeout = setTimeout;\n } else {\n cachedSetTimeout = defaultSetTimout;\n }\n } catch (e) {\n cachedSetTimeout = defaultSetTimout;\n }\n try {\n if (typeof clearTimeout === 'function') {\n cachedClearTimeout = clearTimeout;\n } else {\n cachedClearTimeout = defaultClearTimeout;\n }\n } catch (e) {\n cachedClearTimeout = defaultClearTimeout;\n }\n} ())\nfunction runTimeout(fun) {\n if (cachedSetTimeout === setTimeout) {\n //normal enviroments in sane situations\n return setTimeout(fun, 0);\n }\n // if setTimeout wasn't available but was latter defined\n if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\n cachedSetTimeout = setTimeout;\n return setTimeout(fun, 0);\n }\n try {\n // when when somebody has screwed with setTimeout but no I.E. maddness\n return cachedSetTimeout(fun, 0);\n } catch(e){\n try {\n // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n return cachedSetTimeout.call(null, fun, 0);\n } catch(e){\n // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\n return cachedSetTimeout.call(this, fun, 0);\n }\n }\n\n\n}\nfunction runClearTimeout(marker) {\n if (cachedClearTimeout === clearTimeout) {\n //normal enviroments in sane situations\n return clearTimeout(marker);\n }\n // if clearTimeout wasn't available but was latter defined\n if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\n cachedClearTimeout = clearTimeout;\n return clearTimeout(marker);\n }\n try {\n // when when somebody has screwed with setTimeout but no I.E. maddness\n return cachedClearTimeout(marker);\n } catch (e){\n try {\n // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n return cachedClearTimeout.call(null, marker);\n } catch (e){\n // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\n // Some versions of I.E. have different rules for clearTimeout vs setTimeout\n return cachedClearTimeout.call(this, marker);\n }\n }\n\n\n\n}\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n if (!draining || !currentQueue) {\n return;\n }\n draining = false;\n if (currentQueue.length) {\n queue = currentQueue.concat(queue);\n } else {\n queueIndex = -1;\n }\n if (queue.length) {\n drainQueue();\n }\n}\n\nfunction drainQueue() {\n if (draining) {\n return;\n }\n var timeout = runTimeout(cleanUpNextTick);\n draining = true;\n\n var len = queue.length;\n while(len) {\n currentQueue = queue;\n queue = [];\n while (++queueIndex < len) {\n if (currentQueue) {\n currentQueue[queueIndex].run();\n }\n }\n queueIndex = -1;\n len = queue.length;\n }\n currentQueue = null;\n draining = false;\n runClearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n var args = new Array(arguments.length - 1);\n if (arguments.length > 1) {\n for (var i = 1; i < arguments.length; i++) {\n args[i - 1] = arguments[i];\n }\n }\n queue.push(new Item(fun, args));\n if (queue.length === 1 && !draining) {\n runTimeout(drainQueue);\n }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n this.fun = fun;\n this.array = array;\n}\nItem.prototype.run = function () {\n this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\nprocess.prependListener = noop;\nprocess.prependOnceListener = noop;\n\nprocess.listeners = function (name) { return [] }\n\nprocess.binding = function (name) {\n throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/process/browser.js\n// module id = ./node_modules/process/browser.js\n// module chunks = 0","module.exports = i18n;\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"i18n\"\n// module id = 0\n// module chunks = 0"],"sourceRoot":""} \ No newline at end of file diff --git a/client/src/bundles/UserForms.js b/client/src/bundles/UserForms.js index 886d8a1..67041a1 100644 --- a/client/src/bundles/UserForms.js +++ b/client/src/bundles/UserForms.js @@ -4,6 +4,9 @@ import Schema from 'async-validator'; import i18n from 'i18n'; +const DIRTY_CLASS = 'dirty'; +const FOCUSED_CLASS = 'focused'; + function isVisible(element) { return element.style.display !== 'none' && element.style.visibility !== 'hidden' @@ -157,7 +160,7 @@ class FormStep { const fields = this.step.querySelectorAll('input, textarea, select'); fields.forEach((field) => { - if (isVisible(field) && (!onlyDirty || (onlyDirty && !field.classList.contains('dirty')))) { + if (isVisible(field) && (!onlyDirty || (onlyDirty && field.classList.contains(FOCUSED_CLASS)))) { const label = this.getFieldLabel(field); const holder = this.getHolderForField(field); @@ -248,8 +251,12 @@ class FormStep { enableLiveValidation() { const fields = this.step.querySelectorAll('input, textarea, select'); fields.forEach((field) => { + field.addEventListener('focusin', () => { + field.classList.add(FOCUSED_CLASS); + }); + field.addEventListener('change', () => { - field.classList.add('dirty'); + field.classList.add(DIRTY_CLASS); }); field.addEventListener('focusout', () => { @@ -505,7 +512,7 @@ class UserForm { initAreYouSure() { window.addEventListener('beforeunload', (e) => { - const dirtyFields = this.dom.querySelectorAll('.dirty'); + const dirtyFields = this.dom.querySelectorAll(`.${DIRTY_CLASS}`); if (dirtyFields.length === 0) { return true; } diff --git a/code/Control/UserDefinedFormController.php b/code/Control/UserDefinedFormController.php index 2c759d5..4161100 100644 --- a/code/Control/UserDefinedFormController.php +++ b/code/Control/UserDefinedFormController.php @@ -210,8 +210,24 @@ class UserDefinedFormController extends PageController // Only add customScript if $default or $rules is defined if ($rules) { Requirements::customScript(<<ID); @@ -632,41 +648,22 @@ JS $result .= <<beforeUpdateCMSFields(function (FieldList $fields) { - $fields->removeByName(['MergeField', 'Default', 'Validation', 'DisplayRules']); + $fields->removeByName(['MergeField', 'Default', 'Validation']); }); return parent::getCMSFields(); @@ -98,5 +98,10 @@ class EditableFieldGroup extends EditableFormField if ($this->ExtraClass) { $field->addExtraClass($this->ExtraClass); } + + // if ShowOnLoad is false hide the field + if (!$this->ShowOnLoad) { + $field->addExtraClass($this->ShowOnLoadNice()); + } } } diff --git a/templates/SilverStripe/UserForms/FormField/UserFormsGroupField_holder.ss b/templates/SilverStripe/UserForms/FormField/UserFormsGroupField_holder.ss index 2ec8ece..9010710 100644 --- a/templates/SilverStripe/UserForms/FormField/UserFormsGroupField_holder.ss +++ b/templates/SilverStripe/UserForms/FormField/UserFormsGroupField_holder.ss @@ -1,4 +1,6 @@ -<$Tag class="CompositeField $extraClass<% if $ColumnCount %> multicolumn<% end_if %>"<% if $Tag == 'fieldset' && $RightTitle %> aria-describedby="{$Name}_right_title"<% end_if %>> +<$Tag id="{$Name}" + class="CompositeField $extraClass<% if $ColumnCount %> multicolumn<% end_if %>"<% if $Tag == 'fieldset' && $RightTitle %> + aria-describedby="{$Name}_right_title"<% end_if %>> <% if $Tag == 'fieldset' && $Legend %> $Legend <% end_if %>