@egodesign/form 1.3.0 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -173,6 +173,12 @@ In order to use validations, you must set the correct data type for each field.
173
173
  | `password_repeat` | Use this type alogn with a password field whit an ID of `password`, to validate that both fields have the same value. Mostly intended for password reset forms. |
174
174
  | `single_checkbox` | This type validates that a specific checkbox is checked. Useful for cases like terms and conditions acceptance. |
175
175
 
176
+ In addition you can validate the minimum and maximum length of a field. You can do so by adding the `data-min-length` and `data-max-length` attributes to the field element.
177
+ | Attribute | Description |
178
+ | ---| --- |
179
+ | `data-min-length` | The minimum length of the field. |
180
+ | `data-max-length` | The maximum length of the field. |
181
+
176
182
  ### Masks:
177
183
  Add this class names to the field element in order to apply some masks and filters to your inputs.
178
184
 
@@ -1 +1 @@
1
- "use strict";const e=({element:e,enter:t,time:i,displayType:s,callback:r})=>{e.style.opacity=t?0:1,t&&(e.style.display=s||"block");let a=+new Date;!function s(){e.style.opacity=t?+e.style.opacity+(new Date-a)/(i||200):+e.style.opacity-(new Date-a)/(i||200),a=+new Date,t&&+e.style.opacity<1||!t&&+e.style.opacity>0?window.requestAnimationFrame&&requestAnimationFrame(s)||setTimeout(s,16):(t||(e.style.display="none"),r&&"function"==typeof r&&r())}()},t=({element:e,className:t})=>{if(!e)return!1;for(;e&&!e.classList.contains(t);)e=!!e.parentElement&&e.parentElement;return e},i={default:{empty:"Campo requerido.",invalid:"Campo nó válido."},email:{empty:"El email es requerido.",invalid:"El email no es válido."},message:{empty:"El mensaje es requerido."},password:{empty:"Ingrese una contraseña."},password_repeat:{empty:"Debe repetir la contraseña.",unequal:"Las contraseñas no coindicen."},cuil:{empty:"Campo requerido.",min:"El número debe tener exactamente 11 dígitos.",invalid:"El número ingresado no es válido."},url:{empty:"Campo requerido.",invalid:"URL no válida."},file:{empty:"Campo requerido",min_size:"El tamaño mínimo es [[var]]",max_size:"El tamaño máximo es [[var]]"}};class s{constructor({customValidations:e,classes:t,customValidationMessages:s}){this.customValidations=e,this.validationMessages={...i,...s}||i,this.classes=t}validateField(e){const t=e.dataset.type,i=["radio","checkbox"].includes(t),s=e.classList.contains(this.classes.requiredField),r=e.classList.contains(this.classes.requiredIfFilledField),a=e.querySelector(".form__error"),o=e.querySelector(".form__control"),l=i?e.querySelector(".form__control:checked"):null,n=o?o.getAttribute("name"):"",u=Object.keys(this.customValidations);if(o||this.throwError("control not found."),n||this.throwError("control name not found."),s&&!o.value)return a&&(a.innerText=this.validationMessages[n]?this.validationMessages[n].empty:this.validationMessages.default.empty),this.displayFieldError(o,e,a),!1;if(i&&!l){if(!r)return this.displayFieldError(o,e,a),a&&(a.innerText=this.validationMessages[n]?this.validationMessages[n].empty:this.validationMessages.default.empty),!1}else{switch(t){case"email":if(o.value&&!this.isValidEmail(o.value))return a&&(a.innerText=this.validationMessages.email.invalid),this.displayFieldError(o,e,a),!1;break;case"password_repeat":{const t=document.getElementById("password");if(t&&o.value!=t.value)return a&&(a.innerText=this.validationMessages.password_repeat.unequal),this.displayFieldError(o,e,a),!1;break}case"cuil":case"cuit":if(o.value&&!this.isValidCuitCuil(o.value))return a&&(a.innerText=this.validationMessages.cuil.invalid),this.displayFieldError(o,e,a),!1;break;case"url":if(o.value&&!this.isValidUrl(o.value))return a&&(a.innerText=this.validationMessages.url.invalid),this.displayFieldError(o,e,a),!1;break;case"money":const t=o.dataset.currency?o.dataset.currency:"$";if(""==o.value||o.value==t)return a&&(a.innerText=this.validationMessages.default.empty),this.displayFieldError(o,e,a),!1;break;case"single-checkbox":if(!o.checked)return this.displayFieldError(o,e,a),a&&(a.innerText=this.validationMessages[n]?this.validationMessages[n].empty:this.validationMessages.default.empty),!1}for(const i of u)if(t===i)for(const i of this.customValidations[t])if(!i.condition(o.value))return a&&(a.innerText=i.message||""),this.displayFieldError(o,e,a),!1}return!0}isValidEmail(e){return/(?!.*\.{2})^([a-z\d!#$%&'*+\-/=?^_`{|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+(\.[a-z\d!#$%&'*+\-/=?^_`{|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)*|"((([\t]*\r\n)?[\t]+)?([\x01-\x08\x0b\x0c\x0e-\x1f\x7f\x21\x23-\x5b\x5d-\x7e\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|\\[\x01-\x09\x0b\x0c\x0d-\x7f\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))*(([\t]*\r\n)?[\t]+)?")@(([a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|[a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF][a-z\d\-._~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]*[a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])\.)+([a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|[a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF][a-z\d\-._~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]*[a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])\.?$/i.test(e.toLowerCase())}isValidCuitCuil(e){const t=[5,4,3,2,7,6,5,4,3,2];let i=e.toString().split("");if(11!=i.length)return!1;i=i.map((e=>parseInt(e)));const s=parseInt(i.pop());let r=11-i.reduce(((e,i,s)=>e+i*t[s]),0)%11;return 10==r&&(r=9),11==r&&(r=0),r==s}isValidUrl(e){return!!new RegExp("^(https?:\\/\\/)?((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|((\\d{1,3}\\.){3}\\d{1,3}))(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*(\\?[;&a-z\\d%_.~+=-]*)?(\\#[-a-z\\d_]*)?$","i").test(e)}isValidFileSize(e){let t=null;const i=e.querySelector(".form__control"),s=parseFloat(e.dataset.minSize),r=parseFloat(e.dataset.maxSize),a=e.querySelector(".form__error"),o=i.files[0].name,l=i.files[0].size,n=parseFloat(i.files.length?(l/1048576).toFixed(1):0);n>r||!l?(i.value="",e.classList.remove("--has-file"),i.setAttribute("aria-invalid","true"),e.classList.add(this.classes.fieldHasError)):o?(this.hasFile=!0,e.classList.add("--has-file")):(this.hasFile=!1,e.classList.remove("--has-file")),l?n<s?t=this.validationMessages.file.min_size.replace("[[var]]",s+" MB"):n>r&&(t=this.validationMessages.file.max_size.replace("[[var]]",r+" MB")):t=this.validationMessages.file.empty,t&&(a.innerText=t,this.displayFieldError(i,e,a))}displayFieldError(e,t,i){e.setAttribute("aria-invalid","true"),t.classList.add(this.classes.fieldHasError),this.classes.controlHasError&&e.classList.add(this.classes.controlHasError),i&&i.classList.remove(this.classes.hiddenErrorMessage)}clearControlError(e){e.setAttribute("aria-invalid","false"),this.classes.controlHasError&&e.classList.remove(this.classes.controlHasError);const i=t({element:e,className:"form__field"}),s=i.querySelector(".form__error");i.classList.remove(this.classes.fieldHasError),s&&(s.innerText="",s.classList.add(this.classes.hiddenErrorMessage))}realTimeValidations(e){e.querySelectorAll('.form__field[data-type="file"]').forEach((e=>{const t=e.querySelector(".form__control");t?.addEventListener("change",(t=>{t.stopPropagation(),this.isValidFileSize(e)}))}))}throwError(e){throw new Error(`EgoForm Error: ${e}`)}}module.exports=class{constructor({element:e,classes:t,submitType:i,submitDataFormat:r,requestHeaders:a,fieldGroups:o,serializerIgnoreList:l,customValidations:n,customValidationMessages:u,onStepChange:d,onValidationError:c,onSubmitStart:h,onSubmitEnd:m,onSuccess:f,onError:p,onBeforeSubmit:F,resetOnSuccess:g,scrollOnError:v,preventSubmit:y,debug:E}){this.form=e,this.submitType=i||"fetch",this.submitDataFormat=r||"formData",this.requestHeaders=a||{},this.actionUrl=this.form.getAttribute("action"),this.submitMethod=this.form.getAttribute("method")||"POST",this.submitBtn=this.form.querySelector('button[type="submit"]')||null,this.classes={requiredField:"--required",requiredIfFilledField:"--required-if-filled",fieldHasError:"--has-error",controlHasError:!1,hiddenErrorMessage:"--hidden",formSubmittingState:"--submitting",buttonSubmittingState:"--loading",clearFieldError:"--clear-error",validateOnBlur:"--validate-onblur",...t},this.isValid=!0,this.validator=new s({customValidations:n||{},classes:this.classes,customValidationMessages:u||null}),this.onValidationError=c??!1,this.onStepChange=d??!1,this.onSubmitStart=h??!1,this.onSubmitEnd=m??!1,this.onSuccess=f??!1,this.onError=p??!1,this.onBeforeSubmit=F??!1,this.fieldGroups=o??!1,this.hasFile=!1,this.serializerIgnoreList=l||[],this.resetOnSuccess=g??!0,this.scrollOnError=v??!0,this.currentStep=this.form.querySelector(".form__step")?parseInt(this.form.querySelector(".form__step.--active").dataset.step):0,this.currentStepOptional=!1,this.stepChanging=!1,this.preventSubmit=y??!1,this.debug=E??!1,this.declareHandlers(),this.debug&&this.showLog("initialized!")}submit(){this.preventSubmit||this.resumeSubmit()}resumeSubmit(){this.debug&&this.showLog(`submitting using ${this.submitType}!`),this.submittingForm(!0),this.isValid=!0;const e=[];if(this.form.querySelectorAll(".form__field").forEach((t=>{this.validator.validateField(t)||(e.push(t.querySelector(".form__control")?.name),this.isValid=!1)})),this.isValid)this.debug?(this.showLog("the form was submitted!"),this.showLog(this.serializeData(),"data"),setTimeout((()=>{this.submittingForm(!1)}),1e3)):"fetch"==this.submitType?fetch(this.actionUrl,{method:this.submitMethod,headers:"json"===this.submitDataFormat?{"Content-Type":"application/json",...this.requestHeaders}:{...this.requestHeaders},body:"json"===this.submitDataFormat?JSON.stringify(this.serializeData()):this.serializeData(!0)}).then((e=>{200===e.status||201===e.status?(this.resetOnSuccess&&this.reset(),"function"==typeof this.onSuccess&&this.onSuccess(e)):"function"==typeof this.onError&&this.onError(e)})).catch((e=>{"function"==typeof this.onError&&this.onError(e)})).finally((()=>{this.submittingForm(!1)})):this.form.submit();else{if(this.submittingForm(!1),"function"==typeof this.onValidationError&&this.onValidationError(e),this.debug&&this.showLog(`this fields have failed validation: ${e.toString().replace(/,/g,", ")}.`),this.scrollOnError){const e=this.form.querySelector(`.form__field.${this.classes.fieldHasError}`);(e=>{const t=e.getBoundingClientRect();return t.top>=0&&t.left>=0&&t.bottom<=(window.innerHeight||document.documentElement.clientHeight)&&t.right<=(window.innerWidth||document.documentElement.clientWidth)})(e)||e.scrollIntoView({behavior:"smooth"})}this.debug&&this.showLog("there are invalid fields.")}}submittingForm(e){let t=document.getElementsByTagName("body").item(0);e?(this.form.classList.add(this.classes.formSubmittingState),this.submitBtn.classList.add(this.classes.buttonSubmittingState),t.classList.add("--block"),"function"==typeof this.onSubmitStart&&this.onSubmitStart()):(this.form.classList.remove(this.classes.formSubmittingState),this.submitBtn.classList.remove(this.classes.buttonSubmittingState),t.classList.remove("--block"),"function"==typeof this.onSubmitEnd&&this.onSubmitEnd())}serializeData(e=!1){const t=new FormData(this.form),i={};for(const e of t)if(!this.serializerIgnoreList.includes(e[0])){if(e[1]instanceof File&&!e[1].size&&!e[1].name)continue;i[e[0]]=e[1]}if(this.fieldGroups)for(const e in this.fieldGroups)if(Object.hasOwnProperty.call(this.fieldGroups,e)){let s=[{}];for(const r of this.fieldGroups[e])s[0][r]=t.get(r),delete i[r];i[e]=s}return e?t:i}reset(){this.form.reset(),this.form.querySelectorAll(".form__field").forEach((e=>e.classList.remove("--filled",`${this.classes.fieldHasError}`))),this.form.querySelectorAll(".form__control").forEach((e=>e.setAttribute("aria-invalid","false"))),this.currentStep&&this.changeStep(1)}changeStep(t){if(!this.stepChanging){const i=this.currentStepOptional?this.currentStep+"b":this.currentStep,s=this.form.querySelector('[data-step="'+i+'"]'),r=s.querySelectorAll(`.${this.classes.requiredField}`),a="next"===t?this.currentStep+1:"prev"!==t||this.currentStepOptional?"optional"===t?this.currentStep+"b":this.currentStep:this.currentStep-1,o=this.form.querySelector('[data-step="'+a+'"]');(this.currentStep!==a||this.currentStepOptional)&&(this.stepChanging=!0,this.isValid=!0,setTimeout((()=>{!r||"next"!==t&&"optional"!==t||r.forEach((e=>{this.validator.validateField(e)||(this.isValid=!1)})),s&&o&&this.isValid?e({element:s,enter:!1,time:200,displayType:"flex",callback:()=>{s.classList.remove("--active"),e({element:o,enter:!0,time:200,displayType:"flex",callback:()=>{o.classList.add("--active"),this.stepChanging=!1,this.currentStepOptional="optional"===t,this.currentStep=parseInt(a),"function"==typeof this.onStepChange&&this.onStepChange(i,a)}})}}):this.stepChanging=!1}),50))}}nextStep(){this.changeStep("next")}optionalStep(){this.changeStep("optional")}prevStep(){this.changeStep("prev")}isControlFilled(e){let t=e.parentElement;""!==e.value?t.classList.add("--filled"):t.classList.remove("--filled")}filterNumber(e,t=[]){const i=t.join(""),s=new RegExp("[^"+i+"0-9]","g");return e.toString().replace(s,"")}filterFormattedQuantity(e,t=".",i=",",s){const r=i?e.toString().split(i):[e],a=r[0].replace(/\B(?=(\d{3})+(?!\d))/g,t);let o="";return o=s>0&&r[1]&&r[1].length?a+i+r[1].slice(0,s):a,o}filterMoneyAmount(e,t="$",i=".",s=",",r){if(!e||e==t)return"";let a=this.filterNumber(e,[s||""]);return a=this.filterFormattedQuantity(a,i,s,r),`${t} ${a}`}filterPhoneNumber(e){return e.replace(/[^\d+\-() ]*/g,"")}togglePasswordVisibility(e){this.debug&&this.showLog("Password visibility toggled!");const t=e.parentElement.querySelector(".form__control");if(t){const i="password"===t.getAttribute("type")?"text":"password";t.setAttribute("type",i),e.classList.toggle("--hide")}}declareHandlers(){const e=this;if(!this.submitBtn)throw new Error(`There's no submit button in this form "${this.form.id}".`);this.submitBtn.addEventListener("click",(function(t){t.preventDefault(),"function"==typeof e.onBeforeSubmit&&e.onBeforeSubmit(),e.submit()})),this.validator.realTimeValidations(this.form),e.form.querySelectorAll(`.form__field.${e.classes.validateOnBlur}`).forEach((e=>{console.log("ONBLUR",e),e.querySelector(".form__control").addEventListener("blur",(()=>{this.validator.validateField(e)||(this.isValid=!1)}))})),this.form.querySelectorAll(".form__next-step").forEach((t=>{t.addEventListener("click",e.nextStep.bind(e))})),this.form.querySelectorAll(".form__optional-step").forEach((t=>{t.addEventListener("click",e.optionalStep.bind(e))})),this.form.querySelectorAll(".form__prev-step").forEach((t=>{t.addEventListener("click",e.prevStep.bind(e))})),this.form.querySelectorAll(".form__control").forEach((e=>{this.isControlFilled(e),e.addEventListener("keyup",(()=>{this.isControlFilled(e)})),e.addEventListener("change",(()=>{this.isControlFilled(e)}))})),this.form.querySelectorAll(".form__control").forEach((e=>{e.addEventListener("focus",(()=>{this.validator.clearControlError(e)}))})),this.form.querySelectorAll("."+this.classes.clearFieldError).forEach((i=>{i.addEventListener("click",(()=>{const s=t({element:i,className:"form__field"});e.validator.clearControlError(s.querySelector(".form__control"))}))})),this.form.querySelectorAll(".form__field.--number input").forEach((e=>{const i=this,s=t({element:e,className:"form__field"}),r=s&&s.dataset.thousandsSeparator?s.dataset.thousandsSeparator:null,a=s&&s.dataset.decimalSeparator?s.dataset.decimalSeparator:"",o=s&&s.dataset.decimals?s.dataset.decimals:"";function l(){e.value=i.filterNumber(e.value,[a])}e.addEventListener("focus",l),e.addEventListener("input",l),e.addEventListener("paste",l),e.addEventListener("blur",(()=>{e.value=r?i.filterFormattedQuantity(e.value,r,a,parseInt(o)):i.filterNumber(e.value)}))})),this.form.querySelectorAll(".form__field.--money-amount input").forEach((e=>{const i=this,s=t({element:e,className:"form__field"}),r=s&&s.dataset.currency?s.dataset.currency:"$",a=s&&s.dataset.thousandsSeparator?s.dataset.thousandsSeparator:".",o=s&&s.dataset.decimalSeparator?s.dataset.decimalSeparator:"",l=s&&s.dataset.decimals?s.dataset.decimals:"";function n(){e.value=i.filterNumber(e.value,[o])}e.addEventListener("focus",n),e.addEventListener("input",n),e.addEventListener("paste",n),e.addEventListener("blur",(()=>{e.value=this.filterMoneyAmount(e.value,r,a,o,parseInt(l))}))})),this.form.querySelectorAll(".form__field.--phone input").forEach((e=>{e.addEventListener("input",(()=>{e.value=this.filterPhoneNumber(e.value)})),e.addEventListener("paste",(()=>{e.value=this.filterPhoneNumber(e.value)}))})),this.form.querySelectorAll(".form__toggle-password-visibility").forEach((e=>{e.addEventListener("click",this.togglePasswordVisibility(e))}))}showLog(e,t="log"){"log"==t?console.log("::EgoForm:: "+e):"data"==t&&(console.log("::EgoForm:: DATA"),console.table(e))}};
1
+ "use strict";const e=({element:e,enter:t,time:i,displayType:s,callback:r})=>{e.style.opacity=t?0:1,t&&(e.style.display=s||"block");let a=+new Date;!function s(){e.style.opacity=t?+e.style.opacity+(new Date-a)/(i||200):+e.style.opacity-(new Date-a)/(i||200),a=+new Date,t&&+e.style.opacity<1||!t&&+e.style.opacity>0?window.requestAnimationFrame&&requestAnimationFrame(s)||setTimeout(s,16):(t||(e.style.display="none"),r&&"function"==typeof r&&r())}()},t=({element:e,className:t})=>{if(!e)return!1;for(;e&&!e.classList.contains(t);)e=!!e.parentElement&&e.parentElement;return e},i={default:{empty:"Campo requerido.",invalid:"Campo nó válido.",minLength:"Debe tener al menos [[var]] caracteres.",maxLength:"Debe tener como máximo [[var]] caracteres."},email:{empty:"El email es requerido.",invalid:"El email no es válido."},message:{empty:"El mensaje es requerido."},password:{empty:"Ingrese una contraseña."},password_repeat:{empty:"Debe repetir la contraseña.",unequal:"Las contraseñas no coindicen."},cuil:{empty:"Campo requerido.",min:"El número debe tener exactamente 11 dígitos.",invalid:"El número ingresado no es válido."},url:{empty:"Campo requerido.",invalid:"URL no válida."},file:{empty:"Campo requerido",min_size:"El tamaño mínimo es [[var]]",max_size:"El tamaño máximo es [[var]]"}};class s{constructor({customValidations:e,classes:t,customValidationMessages:s}){this.customValidations=e,this.validationMessages={...i,...s}||i,this.classes=t}validateField(e){const t=e.dataset.type,i=["radio","checkbox"].includes(t),s=e.classList.contains(this.classes.requiredField),r=e.classList.contains(this.classes.requiredIfFilledField),a=e.querySelector(".form__error"),o=e.querySelector(".form__control"),l=i?e.querySelector(".form__control:checked"):null,n=o?o.getAttribute("name"):"",u=Object.keys(this.customValidations),d=e.dataset.minLength?parseInt(e.dataset.minLength):null,c=e.dataset.maxLength?parseInt(e.dataset.maxLength):null;if(o||this.throwError("control not found."),n||this.throwError("control name not found."),s&&!o.value)return a&&(a.innerText=this.validationMessages[n]?this.validationMessages[n].empty:this.validationMessages.default.empty),this.displayFieldError(o,e,a),!1;if(o.value){if(d&&o.value.length<d)return a&&(a.innerText=this.validationMessages.default.minLength.replace("[[var]]",d)),this.displayFieldError(o,e,a),!1;if(c&&o.value.length>c)return a&&(a.innerText=this.validationMessages.default.maxLength.replace("[[var]]",c)),this.displayFieldError(o,e,a),!1}if(i&&!l){if(!r)return this.displayFieldError(o,e,a),a&&(a.innerText=this.validationMessages[n]?this.validationMessages[n].empty:this.validationMessages.default.empty),!1}else{switch(t){case"email":if(o.value&&!this.isValidEmail(o.value))return a&&(a.innerText=this.validationMessages.email.invalid),this.displayFieldError(o,e,a),!1;break;case"password_repeat":{const t=document.getElementById("password");if(t&&o.value!=t.value)return a&&(a.innerText=this.validationMessages.password_repeat.unequal),this.displayFieldError(o,e,a),!1;break}case"cuil":case"cuit":if(o.value&&!this.isValidCuitCuil(o.value))return a&&(a.innerText=this.validationMessages.cuil.invalid),this.displayFieldError(o,e,a),!1;break;case"url":if(o.value&&!this.isValidUrl(o.value))return a&&(a.innerText=this.validationMessages.url.invalid),this.displayFieldError(o,e,a),!1;break;case"money":const t=o.dataset.currency?o.dataset.currency:"$";if(""==o.value||o.value==t)return a&&(a.innerText=this.validationMessages.default.empty),this.displayFieldError(o,e,a),!1;break;case"single-checkbox":if(!o.checked)return this.displayFieldError(o,e,a),a&&(a.innerText=this.validationMessages[n]?this.validationMessages[n].empty:this.validationMessages.default.empty),!1}for(const i of u)if(t===i)for(const i of this.customValidations[t])if(!i.condition(o.value))return a&&(a.innerText=i.message||""),this.displayFieldError(o,e,a),!1}return!0}isValidEmail(e){return/(?!.*\.{2})^([a-z\d!#$%&'*+\-/=?^_`{|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+(\.[a-z\d!#$%&'*+\-/=?^_`{|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)*|"((([\t]*\r\n)?[\t]+)?([\x01-\x08\x0b\x0c\x0e-\x1f\x7f\x21\x23-\x5b\x5d-\x7e\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|\\[\x01-\x09\x0b\x0c\x0d-\x7f\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))*(([\t]*\r\n)?[\t]+)?")@(([a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|[a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF][a-z\d\-._~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]*[a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])\.)+([a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|[a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF][a-z\d\-._~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]*[a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])\.?$/i.test(e.toLowerCase())}isValidCuitCuil(e){const t=[5,4,3,2,7,6,5,4,3,2];let i=e.toString().replace(/[^0-9]/g,"").split("");if(11!=i.length)return!1;i=i.map((e=>parseInt(e)));const s=parseInt(i.pop());let r=11-i.reduce(((e,i,s)=>e+i*t[s]),0)%11;return 10==r&&(r=9),11==r&&(r=0),r==s}isValidUrl(e){return!!new RegExp("^(https?:\\/\\/)?((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|((\\d{1,3}\\.){3}\\d{1,3}))(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*(\\?[;&a-z\\d%_.~+=-]*)?(\\#[-a-z\\d_]*)?$","i").test(e)}isValidFileSize(e){let t=null;const i=e.querySelector(".form__control"),s=parseFloat(e.dataset.minSize),r=parseFloat(e.dataset.maxSize),a=e.querySelector(".form__error"),o=i.files[0].name,l=i.files[0].size,n=parseFloat(i.files.length?(l/1048576).toFixed(1):0);n>r||!l?(i.value="",e.classList.remove("--has-file"),i.setAttribute("aria-invalid","true"),e.classList.add(this.classes.fieldHasError)):o?(this.hasFile=!0,e.classList.add("--has-file")):(this.hasFile=!1,e.classList.remove("--has-file")),l?n<s?t=this.validationMessages.file.min_size.replace("[[var]]",s+" MB"):n>r&&(t=this.validationMessages.file.max_size.replace("[[var]]",r+" MB")):t=this.validationMessages.file.empty,t&&(a.innerText=t,this.displayFieldError(i,e,a))}displayFieldError(e,t,i){e.setAttribute("aria-invalid","true"),t.classList.add(this.classes.fieldHasError),this.classes.controlHasError&&e.classList.add(this.classes.controlHasError),i&&i.classList.remove(this.classes.hiddenErrorMessage)}clearControlError(e){e.setAttribute("aria-invalid","false"),this.classes.controlHasError&&e.classList.remove(this.classes.controlHasError);const i=t({element:e,className:"form__field"}),s=i.querySelector(".form__error");i.classList.remove(this.classes.fieldHasError),s&&(s.innerText="",s.classList.add(this.classes.hiddenErrorMessage))}realTimeValidations(e){e.querySelectorAll('.form__field[data-type="file"]').forEach((e=>{const t=e.querySelector(".form__control");t?.addEventListener("change",(t=>{t.stopPropagation(),this.isValidFileSize(e)}))}))}throwError(e){throw new Error(`EgoForm Error: ${e}`)}}module.exports=class{constructor({element:e,classes:t,submitType:i,submitDataFormat:r,requestHeaders:a,fieldGroups:o,serializerIgnoreList:l,customValidations:n,customValidationMessages:u,onStepChange:d,onValidationError:c,onSubmitStart:h,onSubmitEnd:m,onSuccess:f,onError:p,onBeforeSubmit:F,resetOnSuccess:g,scrollOnError:v,preventSubmit:y,debug:E}){this.form=e,this.submitType=i||"fetch",this.submitDataFormat=r||"formData",this.requestHeaders=a||{},this.actionUrl=this.form.getAttribute("action"),this.submitMethod=this.form.getAttribute("method")||"POST",this.submitBtn=this.form.querySelector('button[type="submit"]')||null,this.classes={requiredField:"--required",requiredIfFilledField:"--required-if-filled",fieldHasError:"--has-error",controlHasError:!1,hiddenErrorMessage:"--hidden",formSubmittingState:"--submitting",buttonSubmittingState:"--loading",clearFieldError:"--clear-error",validateOnBlur:"--validate-onblur",...t},this.isValid=!0,this.validator=new s({customValidations:n||{},classes:this.classes,customValidationMessages:u||null}),this.onValidationError=c??!1,this.onStepChange=d??!1,this.onSubmitStart=h??!1,this.onSubmitEnd=m??!1,this.onSuccess=f??!1,this.onError=p??!1,this.onBeforeSubmit=F??!1,this.fieldGroups=o??!1,this.hasFile=!1,this.serializerIgnoreList=l||[],this.resetOnSuccess=g??!0,this.scrollOnError=v??!0,this.currentStep=this.form.querySelector(".form__step")?parseInt(this.form.querySelector(".form__step.--active").dataset.step):0,this.currentStepOptional=!1,this.stepChanging=!1,this.preventSubmit=y??!1,this.debug=E??!1,this.declareHandlers(),this.debug&&this.showLog("initialized!")}submit(){this.preventSubmit||this.resumeSubmit()}resumeSubmit(){this.debug&&this.showLog(`submitting using ${this.submitType}!`),this.submittingForm(!0),this.isValid=!0;const e=[];if(this.form.querySelectorAll(".form__field").forEach((t=>{this.validator.validateField(t)||(e.push(t.querySelector(".form__control")?.name),this.isValid=!1)})),this.isValid)this.debug?(this.showLog("the form was submitted!"),this.showLog(this.serializeData(),"data"),setTimeout((()=>{this.submittingForm(!1)}),1e3)):"fetch"==this.submitType?fetch(this.actionUrl,{method:this.submitMethod,headers:"json"===this.submitDataFormat?{"Content-Type":"application/json",...this.requestHeaders}:{...this.requestHeaders},body:"json"===this.submitDataFormat?JSON.stringify(this.serializeData()):this.serializeData(!0)}).then((e=>{200===e.status||201===e.status?(this.resetOnSuccess&&this.reset(),"function"==typeof this.onSuccess&&this.onSuccess(e)):"function"==typeof this.onError&&this.onError(e)})).catch((e=>{"function"==typeof this.onError&&this.onError(e)})).finally((()=>{this.submittingForm(!1)})):this.form.submit();else{if(this.submittingForm(!1),"function"==typeof this.onValidationError&&this.onValidationError(e),this.debug&&this.showLog(`this fields have failed validation: ${e.toString().replace(/,/g,", ")}.`),this.scrollOnError){const e=this.form.querySelector(`.form__field.${this.classes.fieldHasError}`);(e=>{const t=e.getBoundingClientRect();return t.top>=0&&t.left>=0&&t.bottom<=(window.innerHeight||document.documentElement.clientHeight)&&t.right<=(window.innerWidth||document.documentElement.clientWidth)})(e)||e.scrollIntoView({behavior:"smooth"})}this.debug&&this.showLog("there are invalid fields.")}}submittingForm(e){let t=document.getElementsByTagName("body").item(0);e?(this.form.classList.add(this.classes.formSubmittingState),this.submitBtn.classList.add(this.classes.buttonSubmittingState),t.classList.add("--block"),"function"==typeof this.onSubmitStart&&this.onSubmitStart()):(this.form.classList.remove(this.classes.formSubmittingState),this.submitBtn.classList.remove(this.classes.buttonSubmittingState),t.classList.remove("--block"),"function"==typeof this.onSubmitEnd&&this.onSubmitEnd())}serializeData(e=!1){const t=new FormData(this.form),i={};for(const e of t)if(!this.serializerIgnoreList.includes(e[0])){if(e[1]instanceof File&&!e[1].size&&!e[1].name)continue;i[e[0]]=e[1]}if(this.fieldGroups)for(const e in this.fieldGroups)if(Object.hasOwnProperty.call(this.fieldGroups,e)){let s=[{}];for(const r of this.fieldGroups[e])s[0][r]=t.get(r),delete i[r];i[e]=s}return e?t:i}reset(){this.form.reset(),this.form.querySelectorAll(".form__field").forEach((e=>e.classList.remove("--filled",`${this.classes.fieldHasError}`))),this.form.querySelectorAll(".form__control").forEach((e=>e.setAttribute("aria-invalid","false"))),this.currentStep&&this.changeStep(1)}changeStep(t){if(!this.stepChanging){const i=this.currentStepOptional?this.currentStep+"b":this.currentStep,s=this.form.querySelector('[data-step="'+i+'"]'),r=s.querySelectorAll(`.${this.classes.requiredField}`),a="next"===t?this.currentStep+1:"prev"!==t||this.currentStepOptional?"optional"===t?this.currentStep+"b":this.currentStep:this.currentStep-1,o=this.form.querySelector('[data-step="'+a+'"]');(this.currentStep!==a||this.currentStepOptional)&&(this.stepChanging=!0,this.isValid=!0,setTimeout((()=>{!r||"next"!==t&&"optional"!==t||r.forEach((e=>{this.validator.validateField(e)||(this.isValid=!1)})),s&&o&&this.isValid?e({element:s,enter:!1,time:200,displayType:"flex",callback:()=>{s.classList.remove("--active"),e({element:o,enter:!0,time:200,displayType:"flex",callback:()=>{o.classList.add("--active"),this.stepChanging=!1,this.currentStepOptional="optional"===t,this.currentStep=parseInt(a),"function"==typeof this.onStepChange&&this.onStepChange(i,a)}})}}):this.stepChanging=!1}),50))}}nextStep(){this.changeStep("next")}optionalStep(){this.changeStep("optional")}prevStep(){this.changeStep("prev")}isControlFilled(e){let t=e.parentElement;""!==e.value?t.classList.add("--filled"):t.classList.remove("--filled")}filterNumber(e,t=[]){const i=t.join(""),s=new RegExp("[^"+i+"0-9]","g");return e.toString().replace(s,"")}filterFormattedQuantity(e,t=".",i=",",s){const r=i?e.toString().split(i):[e],a=r[0].replace(/\B(?=(\d{3})+(?!\d))/g,t);let o="";return o=s>0&&r[1]&&r[1].length?a+i+r[1].slice(0,s):a,o}filterMoneyAmount(e,t="$",i=".",s=",",r){if(!e||e==t)return"";let a=this.filterNumber(e,[s||""]);return a=this.filterFormattedQuantity(a,i,s,r),`${t} ${a}`}filterPhoneNumber(e){return e.replace(/[^\d+\-() ]*/g,"")}togglePasswordVisibility(e){this.debug&&this.showLog("Password visibility toggled!");const t=e.parentElement.querySelector(".form__control");if(t){const i="password"===t.getAttribute("type")?"text":"password";t.setAttribute("type",i),e.classList.toggle("--hide")}}declareHandlers(){const e=this;if(!this.submitBtn)throw new Error(`There's no submit button in this form "${this.form.id}".`);this.submitBtn.addEventListener("click",(function(t){t.preventDefault(),"function"==typeof e.onBeforeSubmit&&e.onBeforeSubmit(),e.submit()})),this.validator.realTimeValidations(this.form),e.form.querySelectorAll(`.form__field.${e.classes.validateOnBlur}`).forEach((e=>{console.log("ONBLUR",e),e.querySelector(".form__control").addEventListener("blur",(()=>{this.validator.validateField(e)||(this.isValid=!1)}))})),this.form.querySelectorAll(".form__next-step").forEach((t=>{t.addEventListener("click",e.nextStep.bind(e))})),this.form.querySelectorAll(".form__optional-step").forEach((t=>{t.addEventListener("click",e.optionalStep.bind(e))})),this.form.querySelectorAll(".form__prev-step").forEach((t=>{t.addEventListener("click",e.prevStep.bind(e))})),this.form.querySelectorAll(".form__control").forEach((e=>{this.isControlFilled(e),e.addEventListener("keyup",(()=>{this.isControlFilled(e)})),e.addEventListener("change",(()=>{this.isControlFilled(e)}))})),this.form.querySelectorAll(".form__control").forEach((e=>{e.addEventListener("focus",(()=>{this.validator.clearControlError(e)}))})),this.form.querySelectorAll("."+this.classes.clearFieldError).forEach((i=>{i.addEventListener("click",(()=>{const s=t({element:i,className:"form__field"});e.validator.clearControlError(s.querySelector(".form__control"))}))})),this.form.querySelectorAll(".form__field.--number input").forEach((e=>{const i=this,s=t({element:e,className:"form__field"}),r=s&&s.dataset.thousandsSeparator?s.dataset.thousandsSeparator:null,a=s&&s.dataset.decimalSeparator?s.dataset.decimalSeparator:"",o=s&&s.dataset.decimals?s.dataset.decimals:"";function l(){e.value=i.filterNumber(e.value,[a])}e.addEventListener("focus",l),e.addEventListener("input",l),e.addEventListener("paste",l),e.addEventListener("blur",(()=>{e.value=r?i.filterFormattedQuantity(e.value,r,a,parseInt(o)):i.filterNumber(e.value)}))})),this.form.querySelectorAll(".form__field.--money-amount input").forEach((e=>{const i=this,s=t({element:e,className:"form__field"}),r=s&&s.dataset.currency?s.dataset.currency:"$",a=s&&s.dataset.thousandsSeparator?s.dataset.thousandsSeparator:".",o=s&&s.dataset.decimalSeparator?s.dataset.decimalSeparator:"",l=s&&s.dataset.decimals?s.dataset.decimals:"";function n(){e.value=i.filterNumber(e.value,[o])}e.addEventListener("focus",n),e.addEventListener("input",n),e.addEventListener("paste",n),e.addEventListener("blur",(()=>{e.value=this.filterMoneyAmount(e.value,r,a,o,parseInt(l))}))})),this.form.querySelectorAll(".form__field.--phone input").forEach((e=>{e.addEventListener("input",(()=>{e.value=this.filterPhoneNumber(e.value)})),e.addEventListener("paste",(()=>{e.value=this.filterPhoneNumber(e.value)}))})),this.form.querySelectorAll(".form__toggle-password-visibility").forEach((e=>{e.addEventListener("click",this.togglePasswordVisibility(e))}))}showLog(e,t="log"){"log"==t?console.log("::EgoForm:: "+e):"data"==t&&(console.log("::EgoForm:: DATA"),console.table(e))}};
@@ -1 +1 @@
1
- const e=({element:e,enter:t,time:i,displayType:s,callback:r})=>{e.style.opacity=t?0:1,t&&(e.style.display=s||"block");let a=+new Date;!function s(){e.style.opacity=t?+e.style.opacity+(new Date-a)/(i||200):+e.style.opacity-(new Date-a)/(i||200),a=+new Date,t&&+e.style.opacity<1||!t&&+e.style.opacity>0?window.requestAnimationFrame&&requestAnimationFrame(s)||setTimeout(s,16):(t||(e.style.display="none"),r&&"function"==typeof r&&r())}()},t=({element:e,className:t})=>{if(!e)return!1;for(;e&&!e.classList.contains(t);)e=!!e.parentElement&&e.parentElement;return e},i={default:{empty:"Campo requerido.",invalid:"Campo nó válido."},email:{empty:"El email es requerido.",invalid:"El email no es válido."},message:{empty:"El mensaje es requerido."},password:{empty:"Ingrese una contraseña."},password_repeat:{empty:"Debe repetir la contraseña.",unequal:"Las contraseñas no coindicen."},cuil:{empty:"Campo requerido.",min:"El número debe tener exactamente 11 dígitos.",invalid:"El número ingresado no es válido."},url:{empty:"Campo requerido.",invalid:"URL no válida."},file:{empty:"Campo requerido",min_size:"El tamaño mínimo es [[var]]",max_size:"El tamaño máximo es [[var]]"}};class s{constructor({customValidations:e,classes:t,customValidationMessages:s}){this.customValidations=e,this.validationMessages={...i,...s}||i,this.classes=t}validateField(e){const t=e.dataset.type,i=["radio","checkbox"].includes(t),s=e.classList.contains(this.classes.requiredField),r=e.classList.contains(this.classes.requiredIfFilledField),a=e.querySelector(".form__error"),o=e.querySelector(".form__control"),l=i?e.querySelector(".form__control:checked"):null,n=o?o.getAttribute("name"):"",u=Object.keys(this.customValidations);if(o||this.throwError("control not found."),n||this.throwError("control name not found."),s&&!o.value)return a&&(a.innerText=this.validationMessages[n]?this.validationMessages[n].empty:this.validationMessages.default.empty),this.displayFieldError(o,e,a),!1;if(i&&!l){if(!r)return this.displayFieldError(o,e,a),a&&(a.innerText=this.validationMessages[n]?this.validationMessages[n].empty:this.validationMessages.default.empty),!1}else{switch(t){case"email":if(o.value&&!this.isValidEmail(o.value))return a&&(a.innerText=this.validationMessages.email.invalid),this.displayFieldError(o,e,a),!1;break;case"password_repeat":{const t=document.getElementById("password");if(t&&o.value!=t.value)return a&&(a.innerText=this.validationMessages.password_repeat.unequal),this.displayFieldError(o,e,a),!1;break}case"cuil":case"cuit":if(o.value&&!this.isValidCuitCuil(o.value))return a&&(a.innerText=this.validationMessages.cuil.invalid),this.displayFieldError(o,e,a),!1;break;case"url":if(o.value&&!this.isValidUrl(o.value))return a&&(a.innerText=this.validationMessages.url.invalid),this.displayFieldError(o,e,a),!1;break;case"money":const t=o.dataset.currency?o.dataset.currency:"$";if(""==o.value||o.value==t)return a&&(a.innerText=this.validationMessages.default.empty),this.displayFieldError(o,e,a),!1;break;case"single-checkbox":if(!o.checked)return this.displayFieldError(o,e,a),a&&(a.innerText=this.validationMessages[n]?this.validationMessages[n].empty:this.validationMessages.default.empty),!1}for(const i of u)if(t===i)for(const i of this.customValidations[t])if(!i.condition(o.value))return a&&(a.innerText=i.message||""),this.displayFieldError(o,e,a),!1}return!0}isValidEmail(e){return/(?!.*\.{2})^([a-z\d!#$%&'*+\-/=?^_`{|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+(\.[a-z\d!#$%&'*+\-/=?^_`{|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)*|"((([\t]*\r\n)?[\t]+)?([\x01-\x08\x0b\x0c\x0e-\x1f\x7f\x21\x23-\x5b\x5d-\x7e\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|\\[\x01-\x09\x0b\x0c\x0d-\x7f\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))*(([\t]*\r\n)?[\t]+)?")@(([a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|[a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF][a-z\d\-._~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]*[a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])\.)+([a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|[a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF][a-z\d\-._~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]*[a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])\.?$/i.test(e.toLowerCase())}isValidCuitCuil(e){const t=[5,4,3,2,7,6,5,4,3,2];let i=e.toString().split("");if(11!=i.length)return!1;i=i.map((e=>parseInt(e)));const s=parseInt(i.pop());let r=11-i.reduce(((e,i,s)=>e+i*t[s]),0)%11;return 10==r&&(r=9),11==r&&(r=0),r==s}isValidUrl(e){return!!new RegExp("^(https?:\\/\\/)?((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|((\\d{1,3}\\.){3}\\d{1,3}))(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*(\\?[;&a-z\\d%_.~+=-]*)?(\\#[-a-z\\d_]*)?$","i").test(e)}isValidFileSize(e){let t=null;const i=e.querySelector(".form__control"),s=parseFloat(e.dataset.minSize),r=parseFloat(e.dataset.maxSize),a=e.querySelector(".form__error"),o=i.files[0].name,l=i.files[0].size,n=parseFloat(i.files.length?(l/1048576).toFixed(1):0);n>r||!l?(i.value="",e.classList.remove("--has-file"),i.setAttribute("aria-invalid","true"),e.classList.add(this.classes.fieldHasError)):o?(this.hasFile=!0,e.classList.add("--has-file")):(this.hasFile=!1,e.classList.remove("--has-file")),l?n<s?t=this.validationMessages.file.min_size.replace("[[var]]",s+" MB"):n>r&&(t=this.validationMessages.file.max_size.replace("[[var]]",r+" MB")):t=this.validationMessages.file.empty,t&&(a.innerText=t,this.displayFieldError(i,e,a))}displayFieldError(e,t,i){e.setAttribute("aria-invalid","true"),t.classList.add(this.classes.fieldHasError),this.classes.controlHasError&&e.classList.add(this.classes.controlHasError),i&&i.classList.remove(this.classes.hiddenErrorMessage)}clearControlError(e){e.setAttribute("aria-invalid","false"),this.classes.controlHasError&&e.classList.remove(this.classes.controlHasError);const i=t({element:e,className:"form__field"}),s=i.querySelector(".form__error");i.classList.remove(this.classes.fieldHasError),s&&(s.innerText="",s.classList.add(this.classes.hiddenErrorMessage))}realTimeValidations(e){e.querySelectorAll('.form__field[data-type="file"]').forEach((e=>{const t=e.querySelector(".form__control");t?.addEventListener("change",(t=>{t.stopPropagation(),this.isValidFileSize(e)}))}))}throwError(e){throw new Error(`EgoForm Error: ${e}`)}}class r{constructor({element:e,classes:t,submitType:i,submitDataFormat:r,requestHeaders:a,fieldGroups:o,serializerIgnoreList:l,customValidations:n,customValidationMessages:u,onStepChange:d,onValidationError:c,onSubmitStart:h,onSubmitEnd:m,onSuccess:f,onError:p,onBeforeSubmit:F,resetOnSuccess:g,scrollOnError:v,preventSubmit:y,debug:E}){this.form=e,this.submitType=i||"fetch",this.submitDataFormat=r||"formData",this.requestHeaders=a||{},this.actionUrl=this.form.getAttribute("action"),this.submitMethod=this.form.getAttribute("method")||"POST",this.submitBtn=this.form.querySelector('button[type="submit"]')||null,this.classes={requiredField:"--required",requiredIfFilledField:"--required-if-filled",fieldHasError:"--has-error",controlHasError:!1,hiddenErrorMessage:"--hidden",formSubmittingState:"--submitting",buttonSubmittingState:"--loading",clearFieldError:"--clear-error",validateOnBlur:"--validate-onblur",...t},this.isValid=!0,this.validator=new s({customValidations:n||{},classes:this.classes,customValidationMessages:u||null}),this.onValidationError=c??!1,this.onStepChange=d??!1,this.onSubmitStart=h??!1,this.onSubmitEnd=m??!1,this.onSuccess=f??!1,this.onError=p??!1,this.onBeforeSubmit=F??!1,this.fieldGroups=o??!1,this.hasFile=!1,this.serializerIgnoreList=l||[],this.resetOnSuccess=g??!0,this.scrollOnError=v??!0,this.currentStep=this.form.querySelector(".form__step")?parseInt(this.form.querySelector(".form__step.--active").dataset.step):0,this.currentStepOptional=!1,this.stepChanging=!1,this.preventSubmit=y??!1,this.debug=E??!1,this.declareHandlers(),this.debug&&this.showLog("initialized!")}submit(){this.preventSubmit||this.resumeSubmit()}resumeSubmit(){this.debug&&this.showLog(`submitting using ${this.submitType}!`),this.submittingForm(!0),this.isValid=!0;const e=[];if(this.form.querySelectorAll(".form__field").forEach((t=>{this.validator.validateField(t)||(e.push(t.querySelector(".form__control")?.name),this.isValid=!1)})),this.isValid)this.debug?(this.showLog("the form was submitted!"),this.showLog(this.serializeData(),"data"),setTimeout((()=>{this.submittingForm(!1)}),1e3)):"fetch"==this.submitType?fetch(this.actionUrl,{method:this.submitMethod,headers:"json"===this.submitDataFormat?{"Content-Type":"application/json",...this.requestHeaders}:{...this.requestHeaders},body:"json"===this.submitDataFormat?JSON.stringify(this.serializeData()):this.serializeData(!0)}).then((e=>{200===e.status||201===e.status?(this.resetOnSuccess&&this.reset(),"function"==typeof this.onSuccess&&this.onSuccess(e)):"function"==typeof this.onError&&this.onError(e)})).catch((e=>{"function"==typeof this.onError&&this.onError(e)})).finally((()=>{this.submittingForm(!1)})):this.form.submit();else{if(this.submittingForm(!1),"function"==typeof this.onValidationError&&this.onValidationError(e),this.debug&&this.showLog(`this fields have failed validation: ${e.toString().replace(/,/g,", ")}.`),this.scrollOnError){const e=this.form.querySelector(`.form__field.${this.classes.fieldHasError}`);(e=>{const t=e.getBoundingClientRect();return t.top>=0&&t.left>=0&&t.bottom<=(window.innerHeight||document.documentElement.clientHeight)&&t.right<=(window.innerWidth||document.documentElement.clientWidth)})(e)||e.scrollIntoView({behavior:"smooth"})}this.debug&&this.showLog("there are invalid fields.")}}submittingForm(e){let t=document.getElementsByTagName("body").item(0);e?(this.form.classList.add(this.classes.formSubmittingState),this.submitBtn.classList.add(this.classes.buttonSubmittingState),t.classList.add("--block"),"function"==typeof this.onSubmitStart&&this.onSubmitStart()):(this.form.classList.remove(this.classes.formSubmittingState),this.submitBtn.classList.remove(this.classes.buttonSubmittingState),t.classList.remove("--block"),"function"==typeof this.onSubmitEnd&&this.onSubmitEnd())}serializeData(e=!1){const t=new FormData(this.form),i={};for(const e of t)if(!this.serializerIgnoreList.includes(e[0])){if(e[1]instanceof File&&!e[1].size&&!e[1].name)continue;i[e[0]]=e[1]}if(this.fieldGroups)for(const e in this.fieldGroups)if(Object.hasOwnProperty.call(this.fieldGroups,e)){let s=[{}];for(const r of this.fieldGroups[e])s[0][r]=t.get(r),delete i[r];i[e]=s}return e?t:i}reset(){this.form.reset(),this.form.querySelectorAll(".form__field").forEach((e=>e.classList.remove("--filled",`${this.classes.fieldHasError}`))),this.form.querySelectorAll(".form__control").forEach((e=>e.setAttribute("aria-invalid","false"))),this.currentStep&&this.changeStep(1)}changeStep(t){if(!this.stepChanging){const i=this.currentStepOptional?this.currentStep+"b":this.currentStep,s=this.form.querySelector('[data-step="'+i+'"]'),r=s.querySelectorAll(`.${this.classes.requiredField}`),a="next"===t?this.currentStep+1:"prev"!==t||this.currentStepOptional?"optional"===t?this.currentStep+"b":this.currentStep:this.currentStep-1,o=this.form.querySelector('[data-step="'+a+'"]');(this.currentStep!==a||this.currentStepOptional)&&(this.stepChanging=!0,this.isValid=!0,setTimeout((()=>{!r||"next"!==t&&"optional"!==t||r.forEach((e=>{this.validator.validateField(e)||(this.isValid=!1)})),s&&o&&this.isValid?e({element:s,enter:!1,time:200,displayType:"flex",callback:()=>{s.classList.remove("--active"),e({element:o,enter:!0,time:200,displayType:"flex",callback:()=>{o.classList.add("--active"),this.stepChanging=!1,this.currentStepOptional="optional"===t,this.currentStep=parseInt(a),"function"==typeof this.onStepChange&&this.onStepChange(i,a)}})}}):this.stepChanging=!1}),50))}}nextStep(){this.changeStep("next")}optionalStep(){this.changeStep("optional")}prevStep(){this.changeStep("prev")}isControlFilled(e){let t=e.parentElement;""!==e.value?t.classList.add("--filled"):t.classList.remove("--filled")}filterNumber(e,t=[]){const i=t.join(""),s=new RegExp("[^"+i+"0-9]","g");return e.toString().replace(s,"")}filterFormattedQuantity(e,t=".",i=",",s){const r=i?e.toString().split(i):[e],a=r[0].replace(/\B(?=(\d{3})+(?!\d))/g,t);let o="";return o=s>0&&r[1]&&r[1].length?a+i+r[1].slice(0,s):a,o}filterMoneyAmount(e,t="$",i=".",s=",",r){if(!e||e==t)return"";let a=this.filterNumber(e,[s||""]);return a=this.filterFormattedQuantity(a,i,s,r),`${t} ${a}`}filterPhoneNumber(e){return e.replace(/[^\d+\-() ]*/g,"")}togglePasswordVisibility(e){this.debug&&this.showLog("Password visibility toggled!");const t=e.parentElement.querySelector(".form__control");if(t){const i="password"===t.getAttribute("type")?"text":"password";t.setAttribute("type",i),e.classList.toggle("--hide")}}declareHandlers(){const e=this;if(!this.submitBtn)throw new Error(`There's no submit button in this form "${this.form.id}".`);this.submitBtn.addEventListener("click",(function(t){t.preventDefault(),"function"==typeof e.onBeforeSubmit&&e.onBeforeSubmit(),e.submit()})),this.validator.realTimeValidations(this.form),e.form.querySelectorAll(`.form__field.${e.classes.validateOnBlur}`).forEach((e=>{console.log("ONBLUR",e),e.querySelector(".form__control").addEventListener("blur",(()=>{this.validator.validateField(e)||(this.isValid=!1)}))})),this.form.querySelectorAll(".form__next-step").forEach((t=>{t.addEventListener("click",e.nextStep.bind(e))})),this.form.querySelectorAll(".form__optional-step").forEach((t=>{t.addEventListener("click",e.optionalStep.bind(e))})),this.form.querySelectorAll(".form__prev-step").forEach((t=>{t.addEventListener("click",e.prevStep.bind(e))})),this.form.querySelectorAll(".form__control").forEach((e=>{this.isControlFilled(e),e.addEventListener("keyup",(()=>{this.isControlFilled(e)})),e.addEventListener("change",(()=>{this.isControlFilled(e)}))})),this.form.querySelectorAll(".form__control").forEach((e=>{e.addEventListener("focus",(()=>{this.validator.clearControlError(e)}))})),this.form.querySelectorAll("."+this.classes.clearFieldError).forEach((i=>{i.addEventListener("click",(()=>{const s=t({element:i,className:"form__field"});e.validator.clearControlError(s.querySelector(".form__control"))}))})),this.form.querySelectorAll(".form__field.--number input").forEach((e=>{const i=this,s=t({element:e,className:"form__field"}),r=s&&s.dataset.thousandsSeparator?s.dataset.thousandsSeparator:null,a=s&&s.dataset.decimalSeparator?s.dataset.decimalSeparator:"",o=s&&s.dataset.decimals?s.dataset.decimals:"";function l(){e.value=i.filterNumber(e.value,[a])}e.addEventListener("focus",l),e.addEventListener("input",l),e.addEventListener("paste",l),e.addEventListener("blur",(()=>{e.value=r?i.filterFormattedQuantity(e.value,r,a,parseInt(o)):i.filterNumber(e.value)}))})),this.form.querySelectorAll(".form__field.--money-amount input").forEach((e=>{const i=this,s=t({element:e,className:"form__field"}),r=s&&s.dataset.currency?s.dataset.currency:"$",a=s&&s.dataset.thousandsSeparator?s.dataset.thousandsSeparator:".",o=s&&s.dataset.decimalSeparator?s.dataset.decimalSeparator:"",l=s&&s.dataset.decimals?s.dataset.decimals:"";function n(){e.value=i.filterNumber(e.value,[o])}e.addEventListener("focus",n),e.addEventListener("input",n),e.addEventListener("paste",n),e.addEventListener("blur",(()=>{e.value=this.filterMoneyAmount(e.value,r,a,o,parseInt(l))}))})),this.form.querySelectorAll(".form__field.--phone input").forEach((e=>{e.addEventListener("input",(()=>{e.value=this.filterPhoneNumber(e.value)})),e.addEventListener("paste",(()=>{e.value=this.filterPhoneNumber(e.value)}))})),this.form.querySelectorAll(".form__toggle-password-visibility").forEach((e=>{e.addEventListener("click",this.togglePasswordVisibility(e))}))}showLog(e,t="log"){"log"==t?console.log("::EgoForm:: "+e):"data"==t&&(console.log("::EgoForm:: DATA"),console.table(e))}}export{r as default};
1
+ const e=({element:e,enter:t,time:i,displayType:s,callback:r})=>{e.style.opacity=t?0:1,t&&(e.style.display=s||"block");let a=+new Date;!function s(){e.style.opacity=t?+e.style.opacity+(new Date-a)/(i||200):+e.style.opacity-(new Date-a)/(i||200),a=+new Date,t&&+e.style.opacity<1||!t&&+e.style.opacity>0?window.requestAnimationFrame&&requestAnimationFrame(s)||setTimeout(s,16):(t||(e.style.display="none"),r&&"function"==typeof r&&r())}()},t=({element:e,className:t})=>{if(!e)return!1;for(;e&&!e.classList.contains(t);)e=!!e.parentElement&&e.parentElement;return e},i={default:{empty:"Campo requerido.",invalid:"Campo nó válido.",minLength:"Debe tener al menos [[var]] caracteres.",maxLength:"Debe tener como máximo [[var]] caracteres."},email:{empty:"El email es requerido.",invalid:"El email no es válido."},message:{empty:"El mensaje es requerido."},password:{empty:"Ingrese una contraseña."},password_repeat:{empty:"Debe repetir la contraseña.",unequal:"Las contraseñas no coindicen."},cuil:{empty:"Campo requerido.",min:"El número debe tener exactamente 11 dígitos.",invalid:"El número ingresado no es válido."},url:{empty:"Campo requerido.",invalid:"URL no válida."},file:{empty:"Campo requerido",min_size:"El tamaño mínimo es [[var]]",max_size:"El tamaño máximo es [[var]]"}};class s{constructor({customValidations:e,classes:t,customValidationMessages:s}){this.customValidations=e,this.validationMessages={...i,...s}||i,this.classes=t}validateField(e){const t=e.dataset.type,i=["radio","checkbox"].includes(t),s=e.classList.contains(this.classes.requiredField),r=e.classList.contains(this.classes.requiredIfFilledField),a=e.querySelector(".form__error"),o=e.querySelector(".form__control"),l=i?e.querySelector(".form__control:checked"):null,n=o?o.getAttribute("name"):"",u=Object.keys(this.customValidations),d=e.dataset.minLength?parseInt(e.dataset.minLength):null,c=e.dataset.maxLength?parseInt(e.dataset.maxLength):null;if(o||this.throwError("control not found."),n||this.throwError("control name not found."),s&&!o.value)return a&&(a.innerText=this.validationMessages[n]?this.validationMessages[n].empty:this.validationMessages.default.empty),this.displayFieldError(o,e,a),!1;if(o.value){if(d&&o.value.length<d)return a&&(a.innerText=this.validationMessages.default.minLength.replace("[[var]]",d)),this.displayFieldError(o,e,a),!1;if(c&&o.value.length>c)return a&&(a.innerText=this.validationMessages.default.maxLength.replace("[[var]]",c)),this.displayFieldError(o,e,a),!1}if(i&&!l){if(!r)return this.displayFieldError(o,e,a),a&&(a.innerText=this.validationMessages[n]?this.validationMessages[n].empty:this.validationMessages.default.empty),!1}else{switch(t){case"email":if(o.value&&!this.isValidEmail(o.value))return a&&(a.innerText=this.validationMessages.email.invalid),this.displayFieldError(o,e,a),!1;break;case"password_repeat":{const t=document.getElementById("password");if(t&&o.value!=t.value)return a&&(a.innerText=this.validationMessages.password_repeat.unequal),this.displayFieldError(o,e,a),!1;break}case"cuil":case"cuit":if(o.value&&!this.isValidCuitCuil(o.value))return a&&(a.innerText=this.validationMessages.cuil.invalid),this.displayFieldError(o,e,a),!1;break;case"url":if(o.value&&!this.isValidUrl(o.value))return a&&(a.innerText=this.validationMessages.url.invalid),this.displayFieldError(o,e,a),!1;break;case"money":const t=o.dataset.currency?o.dataset.currency:"$";if(""==o.value||o.value==t)return a&&(a.innerText=this.validationMessages.default.empty),this.displayFieldError(o,e,a),!1;break;case"single-checkbox":if(!o.checked)return this.displayFieldError(o,e,a),a&&(a.innerText=this.validationMessages[n]?this.validationMessages[n].empty:this.validationMessages.default.empty),!1}for(const i of u)if(t===i)for(const i of this.customValidations[t])if(!i.condition(o.value))return a&&(a.innerText=i.message||""),this.displayFieldError(o,e,a),!1}return!0}isValidEmail(e){return/(?!.*\.{2})^([a-z\d!#$%&'*+\-/=?^_`{|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+(\.[a-z\d!#$%&'*+\-/=?^_`{|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)*|"((([\t]*\r\n)?[\t]+)?([\x01-\x08\x0b\x0c\x0e-\x1f\x7f\x21\x23-\x5b\x5d-\x7e\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|\\[\x01-\x09\x0b\x0c\x0d-\x7f\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))*(([\t]*\r\n)?[\t]+)?")@(([a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|[a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF][a-z\d\-._~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]*[a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])\.)+([a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|[a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF][a-z\d\-._~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]*[a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])\.?$/i.test(e.toLowerCase())}isValidCuitCuil(e){const t=[5,4,3,2,7,6,5,4,3,2];let i=e.toString().replace(/[^0-9]/g,"").split("");if(11!=i.length)return!1;i=i.map((e=>parseInt(e)));const s=parseInt(i.pop());let r=11-i.reduce(((e,i,s)=>e+i*t[s]),0)%11;return 10==r&&(r=9),11==r&&(r=0),r==s}isValidUrl(e){return!!new RegExp("^(https?:\\/\\/)?((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|((\\d{1,3}\\.){3}\\d{1,3}))(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*(\\?[;&a-z\\d%_.~+=-]*)?(\\#[-a-z\\d_]*)?$","i").test(e)}isValidFileSize(e){let t=null;const i=e.querySelector(".form__control"),s=parseFloat(e.dataset.minSize),r=parseFloat(e.dataset.maxSize),a=e.querySelector(".form__error"),o=i.files[0].name,l=i.files[0].size,n=parseFloat(i.files.length?(l/1048576).toFixed(1):0);n>r||!l?(i.value="",e.classList.remove("--has-file"),i.setAttribute("aria-invalid","true"),e.classList.add(this.classes.fieldHasError)):o?(this.hasFile=!0,e.classList.add("--has-file")):(this.hasFile=!1,e.classList.remove("--has-file")),l?n<s?t=this.validationMessages.file.min_size.replace("[[var]]",s+" MB"):n>r&&(t=this.validationMessages.file.max_size.replace("[[var]]",r+" MB")):t=this.validationMessages.file.empty,t&&(a.innerText=t,this.displayFieldError(i,e,a))}displayFieldError(e,t,i){e.setAttribute("aria-invalid","true"),t.classList.add(this.classes.fieldHasError),this.classes.controlHasError&&e.classList.add(this.classes.controlHasError),i&&i.classList.remove(this.classes.hiddenErrorMessage)}clearControlError(e){e.setAttribute("aria-invalid","false"),this.classes.controlHasError&&e.classList.remove(this.classes.controlHasError);const i=t({element:e,className:"form__field"}),s=i.querySelector(".form__error");i.classList.remove(this.classes.fieldHasError),s&&(s.innerText="",s.classList.add(this.classes.hiddenErrorMessage))}realTimeValidations(e){e.querySelectorAll('.form__field[data-type="file"]').forEach((e=>{const t=e.querySelector(".form__control");t?.addEventListener("change",(t=>{t.stopPropagation(),this.isValidFileSize(e)}))}))}throwError(e){throw new Error(`EgoForm Error: ${e}`)}}class r{constructor({element:e,classes:t,submitType:i,submitDataFormat:r,requestHeaders:a,fieldGroups:o,serializerIgnoreList:l,customValidations:n,customValidationMessages:u,onStepChange:d,onValidationError:c,onSubmitStart:h,onSubmitEnd:m,onSuccess:f,onError:p,onBeforeSubmit:F,resetOnSuccess:g,scrollOnError:v,preventSubmit:y,debug:E}){this.form=e,this.submitType=i||"fetch",this.submitDataFormat=r||"formData",this.requestHeaders=a||{},this.actionUrl=this.form.getAttribute("action"),this.submitMethod=this.form.getAttribute("method")||"POST",this.submitBtn=this.form.querySelector('button[type="submit"]')||null,this.classes={requiredField:"--required",requiredIfFilledField:"--required-if-filled",fieldHasError:"--has-error",controlHasError:!1,hiddenErrorMessage:"--hidden",formSubmittingState:"--submitting",buttonSubmittingState:"--loading",clearFieldError:"--clear-error",validateOnBlur:"--validate-onblur",...t},this.isValid=!0,this.validator=new s({customValidations:n||{},classes:this.classes,customValidationMessages:u||null}),this.onValidationError=c??!1,this.onStepChange=d??!1,this.onSubmitStart=h??!1,this.onSubmitEnd=m??!1,this.onSuccess=f??!1,this.onError=p??!1,this.onBeforeSubmit=F??!1,this.fieldGroups=o??!1,this.hasFile=!1,this.serializerIgnoreList=l||[],this.resetOnSuccess=g??!0,this.scrollOnError=v??!0,this.currentStep=this.form.querySelector(".form__step")?parseInt(this.form.querySelector(".form__step.--active").dataset.step):0,this.currentStepOptional=!1,this.stepChanging=!1,this.preventSubmit=y??!1,this.debug=E??!1,this.declareHandlers(),this.debug&&this.showLog("initialized!")}submit(){this.preventSubmit||this.resumeSubmit()}resumeSubmit(){this.debug&&this.showLog(`submitting using ${this.submitType}!`),this.submittingForm(!0),this.isValid=!0;const e=[];if(this.form.querySelectorAll(".form__field").forEach((t=>{this.validator.validateField(t)||(e.push(t.querySelector(".form__control")?.name),this.isValid=!1)})),this.isValid)this.debug?(this.showLog("the form was submitted!"),this.showLog(this.serializeData(),"data"),setTimeout((()=>{this.submittingForm(!1)}),1e3)):"fetch"==this.submitType?fetch(this.actionUrl,{method:this.submitMethod,headers:"json"===this.submitDataFormat?{"Content-Type":"application/json",...this.requestHeaders}:{...this.requestHeaders},body:"json"===this.submitDataFormat?JSON.stringify(this.serializeData()):this.serializeData(!0)}).then((e=>{200===e.status||201===e.status?(this.resetOnSuccess&&this.reset(),"function"==typeof this.onSuccess&&this.onSuccess(e)):"function"==typeof this.onError&&this.onError(e)})).catch((e=>{"function"==typeof this.onError&&this.onError(e)})).finally((()=>{this.submittingForm(!1)})):this.form.submit();else{if(this.submittingForm(!1),"function"==typeof this.onValidationError&&this.onValidationError(e),this.debug&&this.showLog(`this fields have failed validation: ${e.toString().replace(/,/g,", ")}.`),this.scrollOnError){const e=this.form.querySelector(`.form__field.${this.classes.fieldHasError}`);(e=>{const t=e.getBoundingClientRect();return t.top>=0&&t.left>=0&&t.bottom<=(window.innerHeight||document.documentElement.clientHeight)&&t.right<=(window.innerWidth||document.documentElement.clientWidth)})(e)||e.scrollIntoView({behavior:"smooth"})}this.debug&&this.showLog("there are invalid fields.")}}submittingForm(e){let t=document.getElementsByTagName("body").item(0);e?(this.form.classList.add(this.classes.formSubmittingState),this.submitBtn.classList.add(this.classes.buttonSubmittingState),t.classList.add("--block"),"function"==typeof this.onSubmitStart&&this.onSubmitStart()):(this.form.classList.remove(this.classes.formSubmittingState),this.submitBtn.classList.remove(this.classes.buttonSubmittingState),t.classList.remove("--block"),"function"==typeof this.onSubmitEnd&&this.onSubmitEnd())}serializeData(e=!1){const t=new FormData(this.form),i={};for(const e of t)if(!this.serializerIgnoreList.includes(e[0])){if(e[1]instanceof File&&!e[1].size&&!e[1].name)continue;i[e[0]]=e[1]}if(this.fieldGroups)for(const e in this.fieldGroups)if(Object.hasOwnProperty.call(this.fieldGroups,e)){let s=[{}];for(const r of this.fieldGroups[e])s[0][r]=t.get(r),delete i[r];i[e]=s}return e?t:i}reset(){this.form.reset(),this.form.querySelectorAll(".form__field").forEach((e=>e.classList.remove("--filled",`${this.classes.fieldHasError}`))),this.form.querySelectorAll(".form__control").forEach((e=>e.setAttribute("aria-invalid","false"))),this.currentStep&&this.changeStep(1)}changeStep(t){if(!this.stepChanging){const i=this.currentStepOptional?this.currentStep+"b":this.currentStep,s=this.form.querySelector('[data-step="'+i+'"]'),r=s.querySelectorAll(`.${this.classes.requiredField}`),a="next"===t?this.currentStep+1:"prev"!==t||this.currentStepOptional?"optional"===t?this.currentStep+"b":this.currentStep:this.currentStep-1,o=this.form.querySelector('[data-step="'+a+'"]');(this.currentStep!==a||this.currentStepOptional)&&(this.stepChanging=!0,this.isValid=!0,setTimeout((()=>{!r||"next"!==t&&"optional"!==t||r.forEach((e=>{this.validator.validateField(e)||(this.isValid=!1)})),s&&o&&this.isValid?e({element:s,enter:!1,time:200,displayType:"flex",callback:()=>{s.classList.remove("--active"),e({element:o,enter:!0,time:200,displayType:"flex",callback:()=>{o.classList.add("--active"),this.stepChanging=!1,this.currentStepOptional="optional"===t,this.currentStep=parseInt(a),"function"==typeof this.onStepChange&&this.onStepChange(i,a)}})}}):this.stepChanging=!1}),50))}}nextStep(){this.changeStep("next")}optionalStep(){this.changeStep("optional")}prevStep(){this.changeStep("prev")}isControlFilled(e){let t=e.parentElement;""!==e.value?t.classList.add("--filled"):t.classList.remove("--filled")}filterNumber(e,t=[]){const i=t.join(""),s=new RegExp("[^"+i+"0-9]","g");return e.toString().replace(s,"")}filterFormattedQuantity(e,t=".",i=",",s){const r=i?e.toString().split(i):[e],a=r[0].replace(/\B(?=(\d{3})+(?!\d))/g,t);let o="";return o=s>0&&r[1]&&r[1].length?a+i+r[1].slice(0,s):a,o}filterMoneyAmount(e,t="$",i=".",s=",",r){if(!e||e==t)return"";let a=this.filterNumber(e,[s||""]);return a=this.filterFormattedQuantity(a,i,s,r),`${t} ${a}`}filterPhoneNumber(e){return e.replace(/[^\d+\-() ]*/g,"")}togglePasswordVisibility(e){this.debug&&this.showLog("Password visibility toggled!");const t=e.parentElement.querySelector(".form__control");if(t){const i="password"===t.getAttribute("type")?"text":"password";t.setAttribute("type",i),e.classList.toggle("--hide")}}declareHandlers(){const e=this;if(!this.submitBtn)throw new Error(`There's no submit button in this form "${this.form.id}".`);this.submitBtn.addEventListener("click",(function(t){t.preventDefault(),"function"==typeof e.onBeforeSubmit&&e.onBeforeSubmit(),e.submit()})),this.validator.realTimeValidations(this.form),e.form.querySelectorAll(`.form__field.${e.classes.validateOnBlur}`).forEach((e=>{console.log("ONBLUR",e),e.querySelector(".form__control").addEventListener("blur",(()=>{this.validator.validateField(e)||(this.isValid=!1)}))})),this.form.querySelectorAll(".form__next-step").forEach((t=>{t.addEventListener("click",e.nextStep.bind(e))})),this.form.querySelectorAll(".form__optional-step").forEach((t=>{t.addEventListener("click",e.optionalStep.bind(e))})),this.form.querySelectorAll(".form__prev-step").forEach((t=>{t.addEventListener("click",e.prevStep.bind(e))})),this.form.querySelectorAll(".form__control").forEach((e=>{this.isControlFilled(e),e.addEventListener("keyup",(()=>{this.isControlFilled(e)})),e.addEventListener("change",(()=>{this.isControlFilled(e)}))})),this.form.querySelectorAll(".form__control").forEach((e=>{e.addEventListener("focus",(()=>{this.validator.clearControlError(e)}))})),this.form.querySelectorAll("."+this.classes.clearFieldError).forEach((i=>{i.addEventListener("click",(()=>{const s=t({element:i,className:"form__field"});e.validator.clearControlError(s.querySelector(".form__control"))}))})),this.form.querySelectorAll(".form__field.--number input").forEach((e=>{const i=this,s=t({element:e,className:"form__field"}),r=s&&s.dataset.thousandsSeparator?s.dataset.thousandsSeparator:null,a=s&&s.dataset.decimalSeparator?s.dataset.decimalSeparator:"",o=s&&s.dataset.decimals?s.dataset.decimals:"";function l(){e.value=i.filterNumber(e.value,[a])}e.addEventListener("focus",l),e.addEventListener("input",l),e.addEventListener("paste",l),e.addEventListener("blur",(()=>{e.value=r?i.filterFormattedQuantity(e.value,r,a,parseInt(o)):i.filterNumber(e.value)}))})),this.form.querySelectorAll(".form__field.--money-amount input").forEach((e=>{const i=this,s=t({element:e,className:"form__field"}),r=s&&s.dataset.currency?s.dataset.currency:"$",a=s&&s.dataset.thousandsSeparator?s.dataset.thousandsSeparator:".",o=s&&s.dataset.decimalSeparator?s.dataset.decimalSeparator:"",l=s&&s.dataset.decimals?s.dataset.decimals:"";function n(){e.value=i.filterNumber(e.value,[o])}e.addEventListener("focus",n),e.addEventListener("input",n),e.addEventListener("paste",n),e.addEventListener("blur",(()=>{e.value=this.filterMoneyAmount(e.value,r,a,o,parseInt(l))}))})),this.form.querySelectorAll(".form__field.--phone input").forEach((e=>{e.addEventListener("input",(()=>{e.value=this.filterPhoneNumber(e.value)})),e.addEventListener("paste",(()=>{e.value=this.filterPhoneNumber(e.value)}))})),this.form.querySelectorAll(".form__toggle-password-visibility").forEach((e=>{e.addEventListener("click",this.togglePasswordVisibility(e))}))}showLog(e,t="log"){"log"==t?console.log("::EgoForm:: "+e):"data"==t&&(console.log("::EgoForm:: DATA"),console.table(e))}}export{r as default};
@@ -1 +1 @@
1
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):((e="undefined"!=typeof globalThis?globalThis:e||self).egodesign=e.egodesign||{},e.egodesign.form=t())}(this,(function(){"use strict";const e=({element:e,enter:t,time:i,displayType:s,callback:r})=>{e.style.opacity=t?0:1,t&&(e.style.display=s||"block");let a=+new Date;!function s(){e.style.opacity=t?+e.style.opacity+(new Date-a)/(i||200):+e.style.opacity-(new Date-a)/(i||200),a=+new Date,t&&+e.style.opacity<1||!t&&+e.style.opacity>0?window.requestAnimationFrame&&requestAnimationFrame(s)||setTimeout(s,16):(t||(e.style.display="none"),r&&"function"==typeof r&&r())}()},t=({element:e,className:t})=>{if(!e)return!1;for(;e&&!e.classList.contains(t);)e=!!e.parentElement&&e.parentElement;return e},i={default:{empty:"Campo requerido.",invalid:"Campo nó válido."},email:{empty:"El email es requerido.",invalid:"El email no es válido."},message:{empty:"El mensaje es requerido."},password:{empty:"Ingrese una contraseña."},password_repeat:{empty:"Debe repetir la contraseña.",unequal:"Las contraseñas no coindicen."},cuil:{empty:"Campo requerido.",min:"El número debe tener exactamente 11 dígitos.",invalid:"El número ingresado no es válido."},url:{empty:"Campo requerido.",invalid:"URL no válida."},file:{empty:"Campo requerido",min_size:"El tamaño mínimo es [[var]]",max_size:"El tamaño máximo es [[var]]"}};class s{constructor({customValidations:e,classes:t,customValidationMessages:s}){this.customValidations=e,this.validationMessages={...i,...s}||i,this.classes=t}validateField(e){const t=e.dataset.type,i=["radio","checkbox"].includes(t),s=e.classList.contains(this.classes.requiredField),r=e.classList.contains(this.classes.requiredIfFilledField),a=e.querySelector(".form__error"),o=e.querySelector(".form__control"),l=i?e.querySelector(".form__control:checked"):null,n=o?o.getAttribute("name"):"",u=Object.keys(this.customValidations);if(o||this.throwError("control not found."),n||this.throwError("control name not found."),s&&!o.value)return a&&(a.innerText=this.validationMessages[n]?this.validationMessages[n].empty:this.validationMessages.default.empty),this.displayFieldError(o,e,a),!1;if(i&&!l){if(!r)return this.displayFieldError(o,e,a),a&&(a.innerText=this.validationMessages[n]?this.validationMessages[n].empty:this.validationMessages.default.empty),!1}else{switch(t){case"email":if(o.value&&!this.isValidEmail(o.value))return a&&(a.innerText=this.validationMessages.email.invalid),this.displayFieldError(o,e,a),!1;break;case"password_repeat":{const t=document.getElementById("password");if(t&&o.value!=t.value)return a&&(a.innerText=this.validationMessages.password_repeat.unequal),this.displayFieldError(o,e,a),!1;break}case"cuil":case"cuit":if(o.value&&!this.isValidCuitCuil(o.value))return a&&(a.innerText=this.validationMessages.cuil.invalid),this.displayFieldError(o,e,a),!1;break;case"url":if(o.value&&!this.isValidUrl(o.value))return a&&(a.innerText=this.validationMessages.url.invalid),this.displayFieldError(o,e,a),!1;break;case"money":const t=o.dataset.currency?o.dataset.currency:"$";if(""==o.value||o.value==t)return a&&(a.innerText=this.validationMessages.default.empty),this.displayFieldError(o,e,a),!1;break;case"single-checkbox":if(!o.checked)return this.displayFieldError(o,e,a),a&&(a.innerText=this.validationMessages[n]?this.validationMessages[n].empty:this.validationMessages.default.empty),!1}for(const i of u)if(t===i)for(const i of this.customValidations[t])if(!i.condition(o.value))return a&&(a.innerText=i.message||""),this.displayFieldError(o,e,a),!1}return!0}isValidEmail(e){return/(?!.*\.{2})^([a-z\d!#$%&'*+\-/=?^_`{|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+(\.[a-z\d!#$%&'*+\-/=?^_`{|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)*|"((([\t]*\r\n)?[\t]+)?([\x01-\x08\x0b\x0c\x0e-\x1f\x7f\x21\x23-\x5b\x5d-\x7e\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|\\[\x01-\x09\x0b\x0c\x0d-\x7f\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))*(([\t]*\r\n)?[\t]+)?")@(([a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|[a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF][a-z\d\-._~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]*[a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])\.)+([a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|[a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF][a-z\d\-._~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]*[a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])\.?$/i.test(e.toLowerCase())}isValidCuitCuil(e){const t=[5,4,3,2,7,6,5,4,3,2];let i=e.toString().split("");if(11!=i.length)return!1;i=i.map((e=>parseInt(e)));const s=parseInt(i.pop());let r=11-i.reduce(((e,i,s)=>e+i*t[s]),0)%11;return 10==r&&(r=9),11==r&&(r=0),r==s}isValidUrl(e){return!!new RegExp("^(https?:\\/\\/)?((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|((\\d{1,3}\\.){3}\\d{1,3}))(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*(\\?[;&a-z\\d%_.~+=-]*)?(\\#[-a-z\\d_]*)?$","i").test(e)}isValidFileSize(e){let t=null;const i=e.querySelector(".form__control"),s=parseFloat(e.dataset.minSize),r=parseFloat(e.dataset.maxSize),a=e.querySelector(".form__error"),o=i.files[0].name,l=i.files[0].size,n=parseFloat(i.files.length?(l/1048576).toFixed(1):0);n>r||!l?(i.value="",e.classList.remove("--has-file"),i.setAttribute("aria-invalid","true"),e.classList.add(this.classes.fieldHasError)):o?(this.hasFile=!0,e.classList.add("--has-file")):(this.hasFile=!1,e.classList.remove("--has-file")),l?n<s?t=this.validationMessages.file.min_size.replace("[[var]]",s+" MB"):n>r&&(t=this.validationMessages.file.max_size.replace("[[var]]",r+" MB")):t=this.validationMessages.file.empty,t&&(a.innerText=t,this.displayFieldError(i,e,a))}displayFieldError(e,t,i){e.setAttribute("aria-invalid","true"),t.classList.add(this.classes.fieldHasError),this.classes.controlHasError&&e.classList.add(this.classes.controlHasError),i&&i.classList.remove(this.classes.hiddenErrorMessage)}clearControlError(e){e.setAttribute("aria-invalid","false"),this.classes.controlHasError&&e.classList.remove(this.classes.controlHasError);const i=t({element:e,className:"form__field"}),s=i.querySelector(".form__error");i.classList.remove(this.classes.fieldHasError),s&&(s.innerText="",s.classList.add(this.classes.hiddenErrorMessage))}realTimeValidations(e){e.querySelectorAll('.form__field[data-type="file"]').forEach((e=>{const t=e.querySelector(".form__control");t?.addEventListener("change",(t=>{t.stopPropagation(),this.isValidFileSize(e)}))}))}throwError(e){throw new Error(`EgoForm Error: ${e}`)}}return class{constructor({element:e,classes:t,submitType:i,submitDataFormat:r,requestHeaders:a,fieldGroups:o,serializerIgnoreList:l,customValidations:n,customValidationMessages:u,onStepChange:d,onValidationError:c,onSubmitStart:h,onSubmitEnd:m,onSuccess:f,onError:p,onBeforeSubmit:F,resetOnSuccess:g,scrollOnError:y,preventSubmit:v,debug:E}){this.form=e,this.submitType=i||"fetch",this.submitDataFormat=r||"formData",this.requestHeaders=a||{},this.actionUrl=this.form.getAttribute("action"),this.submitMethod=this.form.getAttribute("method")||"POST",this.submitBtn=this.form.querySelector('button[type="submit"]')||null,this.classes={requiredField:"--required",requiredIfFilledField:"--required-if-filled",fieldHasError:"--has-error",controlHasError:!1,hiddenErrorMessage:"--hidden",formSubmittingState:"--submitting",buttonSubmittingState:"--loading",clearFieldError:"--clear-error",validateOnBlur:"--validate-onblur",...t},this.isValid=!0,this.validator=new s({customValidations:n||{},classes:this.classes,customValidationMessages:u||null}),this.onValidationError=c??!1,this.onStepChange=d??!1,this.onSubmitStart=h??!1,this.onSubmitEnd=m??!1,this.onSuccess=f??!1,this.onError=p??!1,this.onBeforeSubmit=F??!1,this.fieldGroups=o??!1,this.hasFile=!1,this.serializerIgnoreList=l||[],this.resetOnSuccess=g??!0,this.scrollOnError=y??!0,this.currentStep=this.form.querySelector(".form__step")?parseInt(this.form.querySelector(".form__step.--active").dataset.step):0,this.currentStepOptional=!1,this.stepChanging=!1,this.preventSubmit=v??!1,this.debug=E??!1,this.declareHandlers(),this.debug&&this.showLog("initialized!")}submit(){this.preventSubmit||this.resumeSubmit()}resumeSubmit(){this.debug&&this.showLog(`submitting using ${this.submitType}!`),this.submittingForm(!0),this.isValid=!0;const e=[];if(this.form.querySelectorAll(".form__field").forEach((t=>{this.validator.validateField(t)||(e.push(t.querySelector(".form__control")?.name),this.isValid=!1)})),this.isValid)this.debug?(this.showLog("the form was submitted!"),this.showLog(this.serializeData(),"data"),setTimeout((()=>{this.submittingForm(!1)}),1e3)):"fetch"==this.submitType?fetch(this.actionUrl,{method:this.submitMethod,headers:"json"===this.submitDataFormat?{"Content-Type":"application/json",...this.requestHeaders}:{...this.requestHeaders},body:"json"===this.submitDataFormat?JSON.stringify(this.serializeData()):this.serializeData(!0)}).then((e=>{200===e.status||201===e.status?(this.resetOnSuccess&&this.reset(),"function"==typeof this.onSuccess&&this.onSuccess(e)):"function"==typeof this.onError&&this.onError(e)})).catch((e=>{"function"==typeof this.onError&&this.onError(e)})).finally((()=>{this.submittingForm(!1)})):this.form.submit();else{if(this.submittingForm(!1),"function"==typeof this.onValidationError&&this.onValidationError(e),this.debug&&this.showLog(`this fields have failed validation: ${e.toString().replace(/,/g,", ")}.`),this.scrollOnError){const e=this.form.querySelector(`.form__field.${this.classes.fieldHasError}`);(e=>{const t=e.getBoundingClientRect();return t.top>=0&&t.left>=0&&t.bottom<=(window.innerHeight||document.documentElement.clientHeight)&&t.right<=(window.innerWidth||document.documentElement.clientWidth)})(e)||e.scrollIntoView({behavior:"smooth"})}this.debug&&this.showLog("there are invalid fields.")}}submittingForm(e){let t=document.getElementsByTagName("body").item(0);e?(this.form.classList.add(this.classes.formSubmittingState),this.submitBtn.classList.add(this.classes.buttonSubmittingState),t.classList.add("--block"),"function"==typeof this.onSubmitStart&&this.onSubmitStart()):(this.form.classList.remove(this.classes.formSubmittingState),this.submitBtn.classList.remove(this.classes.buttonSubmittingState),t.classList.remove("--block"),"function"==typeof this.onSubmitEnd&&this.onSubmitEnd())}serializeData(e=!1){const t=new FormData(this.form),i={};for(const e of t)if(!this.serializerIgnoreList.includes(e[0])){if(e[1]instanceof File&&!e[1].size&&!e[1].name)continue;i[e[0]]=e[1]}if(this.fieldGroups)for(const e in this.fieldGroups)if(Object.hasOwnProperty.call(this.fieldGroups,e)){let s=[{}];for(const r of this.fieldGroups[e])s[0][r]=t.get(r),delete i[r];i[e]=s}return e?t:i}reset(){this.form.reset(),this.form.querySelectorAll(".form__field").forEach((e=>e.classList.remove("--filled",`${this.classes.fieldHasError}`))),this.form.querySelectorAll(".form__control").forEach((e=>e.setAttribute("aria-invalid","false"))),this.currentStep&&this.changeStep(1)}changeStep(t){if(!this.stepChanging){const i=this.currentStepOptional?this.currentStep+"b":this.currentStep,s=this.form.querySelector('[data-step="'+i+'"]'),r=s.querySelectorAll(`.${this.classes.requiredField}`),a="next"===t?this.currentStep+1:"prev"!==t||this.currentStepOptional?"optional"===t?this.currentStep+"b":this.currentStep:this.currentStep-1,o=this.form.querySelector('[data-step="'+a+'"]');(this.currentStep!==a||this.currentStepOptional)&&(this.stepChanging=!0,this.isValid=!0,setTimeout((()=>{!r||"next"!==t&&"optional"!==t||r.forEach((e=>{this.validator.validateField(e)||(this.isValid=!1)})),s&&o&&this.isValid?e({element:s,enter:!1,time:200,displayType:"flex",callback:()=>{s.classList.remove("--active"),e({element:o,enter:!0,time:200,displayType:"flex",callback:()=>{o.classList.add("--active"),this.stepChanging=!1,this.currentStepOptional="optional"===t,this.currentStep=parseInt(a),"function"==typeof this.onStepChange&&this.onStepChange(i,a)}})}}):this.stepChanging=!1}),50))}}nextStep(){this.changeStep("next")}optionalStep(){this.changeStep("optional")}prevStep(){this.changeStep("prev")}isControlFilled(e){let t=e.parentElement;""!==e.value?t.classList.add("--filled"):t.classList.remove("--filled")}filterNumber(e,t=[]){const i=t.join(""),s=new RegExp("[^"+i+"0-9]","g");return e.toString().replace(s,"")}filterFormattedQuantity(e,t=".",i=",",s){const r=i?e.toString().split(i):[e],a=r[0].replace(/\B(?=(\d{3})+(?!\d))/g,t);let o="";return o=s>0&&r[1]&&r[1].length?a+i+r[1].slice(0,s):a,o}filterMoneyAmount(e,t="$",i=".",s=",",r){if(!e||e==t)return"";let a=this.filterNumber(e,[s||""]);return a=this.filterFormattedQuantity(a,i,s,r),`${t} ${a}`}filterPhoneNumber(e){return e.replace(/[^\d+\-() ]*/g,"")}togglePasswordVisibility(e){this.debug&&this.showLog("Password visibility toggled!");const t=e.parentElement.querySelector(".form__control");if(t){const i="password"===t.getAttribute("type")?"text":"password";t.setAttribute("type",i),e.classList.toggle("--hide")}}declareHandlers(){const e=this;if(!this.submitBtn)throw new Error(`There's no submit button in this form "${this.form.id}".`);this.submitBtn.addEventListener("click",(function(t){t.preventDefault(),"function"==typeof e.onBeforeSubmit&&e.onBeforeSubmit(),e.submit()})),this.validator.realTimeValidations(this.form),e.form.querySelectorAll(`.form__field.${e.classes.validateOnBlur}`).forEach((e=>{console.log("ONBLUR",e),e.querySelector(".form__control").addEventListener("blur",(()=>{this.validator.validateField(e)||(this.isValid=!1)}))})),this.form.querySelectorAll(".form__next-step").forEach((t=>{t.addEventListener("click",e.nextStep.bind(e))})),this.form.querySelectorAll(".form__optional-step").forEach((t=>{t.addEventListener("click",e.optionalStep.bind(e))})),this.form.querySelectorAll(".form__prev-step").forEach((t=>{t.addEventListener("click",e.prevStep.bind(e))})),this.form.querySelectorAll(".form__control").forEach((e=>{this.isControlFilled(e),e.addEventListener("keyup",(()=>{this.isControlFilled(e)})),e.addEventListener("change",(()=>{this.isControlFilled(e)}))})),this.form.querySelectorAll(".form__control").forEach((e=>{e.addEventListener("focus",(()=>{this.validator.clearControlError(e)}))})),this.form.querySelectorAll("."+this.classes.clearFieldError).forEach((i=>{i.addEventListener("click",(()=>{const s=t({element:i,className:"form__field"});e.validator.clearControlError(s.querySelector(".form__control"))}))})),this.form.querySelectorAll(".form__field.--number input").forEach((e=>{const i=this,s=t({element:e,className:"form__field"}),r=s&&s.dataset.thousandsSeparator?s.dataset.thousandsSeparator:null,a=s&&s.dataset.decimalSeparator?s.dataset.decimalSeparator:"",o=s&&s.dataset.decimals?s.dataset.decimals:"";function l(){e.value=i.filterNumber(e.value,[a])}e.addEventListener("focus",l),e.addEventListener("input",l),e.addEventListener("paste",l),e.addEventListener("blur",(()=>{e.value=r?i.filterFormattedQuantity(e.value,r,a,parseInt(o)):i.filterNumber(e.value)}))})),this.form.querySelectorAll(".form__field.--money-amount input").forEach((e=>{const i=this,s=t({element:e,className:"form__field"}),r=s&&s.dataset.currency?s.dataset.currency:"$",a=s&&s.dataset.thousandsSeparator?s.dataset.thousandsSeparator:".",o=s&&s.dataset.decimalSeparator?s.dataset.decimalSeparator:"",l=s&&s.dataset.decimals?s.dataset.decimals:"";function n(){e.value=i.filterNumber(e.value,[o])}e.addEventListener("focus",n),e.addEventListener("input",n),e.addEventListener("paste",n),e.addEventListener("blur",(()=>{e.value=this.filterMoneyAmount(e.value,r,a,o,parseInt(l))}))})),this.form.querySelectorAll(".form__field.--phone input").forEach((e=>{e.addEventListener("input",(()=>{e.value=this.filterPhoneNumber(e.value)})),e.addEventListener("paste",(()=>{e.value=this.filterPhoneNumber(e.value)}))})),this.form.querySelectorAll(".form__toggle-password-visibility").forEach((e=>{e.addEventListener("click",this.togglePasswordVisibility(e))}))}showLog(e,t="log"){"log"==t?console.log("::EgoForm:: "+e):"data"==t&&(console.log("::EgoForm:: DATA"),console.table(e))}}}));
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):((e="undefined"!=typeof globalThis?globalThis:e||self).egodesign=e.egodesign||{},e.egodesign.form=t())}(this,(function(){"use strict";const e=({element:e,enter:t,time:i,displayType:s,callback:r})=>{e.style.opacity=t?0:1,t&&(e.style.display=s||"block");let a=+new Date;!function s(){e.style.opacity=t?+e.style.opacity+(new Date-a)/(i||200):+e.style.opacity-(new Date-a)/(i||200),a=+new Date,t&&+e.style.opacity<1||!t&&+e.style.opacity>0?window.requestAnimationFrame&&requestAnimationFrame(s)||setTimeout(s,16):(t||(e.style.display="none"),r&&"function"==typeof r&&r())}()},t=({element:e,className:t})=>{if(!e)return!1;for(;e&&!e.classList.contains(t);)e=!!e.parentElement&&e.parentElement;return e},i={default:{empty:"Campo requerido.",invalid:"Campo nó válido.",minLength:"Debe tener al menos [[var]] caracteres.",maxLength:"Debe tener como máximo [[var]] caracteres."},email:{empty:"El email es requerido.",invalid:"El email no es válido."},message:{empty:"El mensaje es requerido."},password:{empty:"Ingrese una contraseña."},password_repeat:{empty:"Debe repetir la contraseña.",unequal:"Las contraseñas no coindicen."},cuil:{empty:"Campo requerido.",min:"El número debe tener exactamente 11 dígitos.",invalid:"El número ingresado no es válido."},url:{empty:"Campo requerido.",invalid:"URL no válida."},file:{empty:"Campo requerido",min_size:"El tamaño mínimo es [[var]]",max_size:"El tamaño máximo es [[var]]"}};class s{constructor({customValidations:e,classes:t,customValidationMessages:s}){this.customValidations=e,this.validationMessages={...i,...s}||i,this.classes=t}validateField(e){const t=e.dataset.type,i=["radio","checkbox"].includes(t),s=e.classList.contains(this.classes.requiredField),r=e.classList.contains(this.classes.requiredIfFilledField),a=e.querySelector(".form__error"),o=e.querySelector(".form__control"),l=i?e.querySelector(".form__control:checked"):null,n=o?o.getAttribute("name"):"",u=Object.keys(this.customValidations),d=e.dataset.minLength?parseInt(e.dataset.minLength):null,c=e.dataset.maxLength?parseInt(e.dataset.maxLength):null;if(o||this.throwError("control not found."),n||this.throwError("control name not found."),s&&!o.value)return a&&(a.innerText=this.validationMessages[n]?this.validationMessages[n].empty:this.validationMessages.default.empty),this.displayFieldError(o,e,a),!1;if(o.value){if(d&&o.value.length<d)return a&&(a.innerText=this.validationMessages.default.minLength.replace("[[var]]",d)),this.displayFieldError(o,e,a),!1;if(c&&o.value.length>c)return a&&(a.innerText=this.validationMessages.default.maxLength.replace("[[var]]",c)),this.displayFieldError(o,e,a),!1}if(i&&!l){if(!r)return this.displayFieldError(o,e,a),a&&(a.innerText=this.validationMessages[n]?this.validationMessages[n].empty:this.validationMessages.default.empty),!1}else{switch(t){case"email":if(o.value&&!this.isValidEmail(o.value))return a&&(a.innerText=this.validationMessages.email.invalid),this.displayFieldError(o,e,a),!1;break;case"password_repeat":{const t=document.getElementById("password");if(t&&o.value!=t.value)return a&&(a.innerText=this.validationMessages.password_repeat.unequal),this.displayFieldError(o,e,a),!1;break}case"cuil":case"cuit":if(o.value&&!this.isValidCuitCuil(o.value))return a&&(a.innerText=this.validationMessages.cuil.invalid),this.displayFieldError(o,e,a),!1;break;case"url":if(o.value&&!this.isValidUrl(o.value))return a&&(a.innerText=this.validationMessages.url.invalid),this.displayFieldError(o,e,a),!1;break;case"money":const t=o.dataset.currency?o.dataset.currency:"$";if(""==o.value||o.value==t)return a&&(a.innerText=this.validationMessages.default.empty),this.displayFieldError(o,e,a),!1;break;case"single-checkbox":if(!o.checked)return this.displayFieldError(o,e,a),a&&(a.innerText=this.validationMessages[n]?this.validationMessages[n].empty:this.validationMessages.default.empty),!1}for(const i of u)if(t===i)for(const i of this.customValidations[t])if(!i.condition(o.value))return a&&(a.innerText=i.message||""),this.displayFieldError(o,e,a),!1}return!0}isValidEmail(e){return/(?!.*\.{2})^([a-z\d!#$%&'*+\-/=?^_`{|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+(\.[a-z\d!#$%&'*+\-/=?^_`{|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)*|"((([\t]*\r\n)?[\t]+)?([\x01-\x08\x0b\x0c\x0e-\x1f\x7f\x21\x23-\x5b\x5d-\x7e\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|\\[\x01-\x09\x0b\x0c\x0d-\x7f\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))*(([\t]*\r\n)?[\t]+)?")@(([a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|[a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF][a-z\d\-._~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]*[a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])\.)+([a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|[a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF][a-z\d\-._~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]*[a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])\.?$/i.test(e.toLowerCase())}isValidCuitCuil(e){const t=[5,4,3,2,7,6,5,4,3,2];let i=e.toString().replace(/[^0-9]/g,"").split("");if(11!=i.length)return!1;i=i.map((e=>parseInt(e)));const s=parseInt(i.pop());let r=11-i.reduce(((e,i,s)=>e+i*t[s]),0)%11;return 10==r&&(r=9),11==r&&(r=0),r==s}isValidUrl(e){return!!new RegExp("^(https?:\\/\\/)?((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|((\\d{1,3}\\.){3}\\d{1,3}))(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*(\\?[;&a-z\\d%_.~+=-]*)?(\\#[-a-z\\d_]*)?$","i").test(e)}isValidFileSize(e){let t=null;const i=e.querySelector(".form__control"),s=parseFloat(e.dataset.minSize),r=parseFloat(e.dataset.maxSize),a=e.querySelector(".form__error"),o=i.files[0].name,l=i.files[0].size,n=parseFloat(i.files.length?(l/1048576).toFixed(1):0);n>r||!l?(i.value="",e.classList.remove("--has-file"),i.setAttribute("aria-invalid","true"),e.classList.add(this.classes.fieldHasError)):o?(this.hasFile=!0,e.classList.add("--has-file")):(this.hasFile=!1,e.classList.remove("--has-file")),l?n<s?t=this.validationMessages.file.min_size.replace("[[var]]",s+" MB"):n>r&&(t=this.validationMessages.file.max_size.replace("[[var]]",r+" MB")):t=this.validationMessages.file.empty,t&&(a.innerText=t,this.displayFieldError(i,e,a))}displayFieldError(e,t,i){e.setAttribute("aria-invalid","true"),t.classList.add(this.classes.fieldHasError),this.classes.controlHasError&&e.classList.add(this.classes.controlHasError),i&&i.classList.remove(this.classes.hiddenErrorMessage)}clearControlError(e){e.setAttribute("aria-invalid","false"),this.classes.controlHasError&&e.classList.remove(this.classes.controlHasError);const i=t({element:e,className:"form__field"}),s=i.querySelector(".form__error");i.classList.remove(this.classes.fieldHasError),s&&(s.innerText="",s.classList.add(this.classes.hiddenErrorMessage))}realTimeValidations(e){e.querySelectorAll('.form__field[data-type="file"]').forEach((e=>{const t=e.querySelector(".form__control");t?.addEventListener("change",(t=>{t.stopPropagation(),this.isValidFileSize(e)}))}))}throwError(e){throw new Error(`EgoForm Error: ${e}`)}}return class{constructor({element:e,classes:t,submitType:i,submitDataFormat:r,requestHeaders:a,fieldGroups:o,serializerIgnoreList:l,customValidations:n,customValidationMessages:u,onStepChange:d,onValidationError:c,onSubmitStart:h,onSubmitEnd:m,onSuccess:f,onError:p,onBeforeSubmit:F,resetOnSuccess:g,scrollOnError:v,preventSubmit:y,debug:E}){this.form=e,this.submitType=i||"fetch",this.submitDataFormat=r||"formData",this.requestHeaders=a||{},this.actionUrl=this.form.getAttribute("action"),this.submitMethod=this.form.getAttribute("method")||"POST",this.submitBtn=this.form.querySelector('button[type="submit"]')||null,this.classes={requiredField:"--required",requiredIfFilledField:"--required-if-filled",fieldHasError:"--has-error",controlHasError:!1,hiddenErrorMessage:"--hidden",formSubmittingState:"--submitting",buttonSubmittingState:"--loading",clearFieldError:"--clear-error",validateOnBlur:"--validate-onblur",...t},this.isValid=!0,this.validator=new s({customValidations:n||{},classes:this.classes,customValidationMessages:u||null}),this.onValidationError=c??!1,this.onStepChange=d??!1,this.onSubmitStart=h??!1,this.onSubmitEnd=m??!1,this.onSuccess=f??!1,this.onError=p??!1,this.onBeforeSubmit=F??!1,this.fieldGroups=o??!1,this.hasFile=!1,this.serializerIgnoreList=l||[],this.resetOnSuccess=g??!0,this.scrollOnError=v??!0,this.currentStep=this.form.querySelector(".form__step")?parseInt(this.form.querySelector(".form__step.--active").dataset.step):0,this.currentStepOptional=!1,this.stepChanging=!1,this.preventSubmit=y??!1,this.debug=E??!1,this.declareHandlers(),this.debug&&this.showLog("initialized!")}submit(){this.preventSubmit||this.resumeSubmit()}resumeSubmit(){this.debug&&this.showLog(`submitting using ${this.submitType}!`),this.submittingForm(!0),this.isValid=!0;const e=[];if(this.form.querySelectorAll(".form__field").forEach((t=>{this.validator.validateField(t)||(e.push(t.querySelector(".form__control")?.name),this.isValid=!1)})),this.isValid)this.debug?(this.showLog("the form was submitted!"),this.showLog(this.serializeData(),"data"),setTimeout((()=>{this.submittingForm(!1)}),1e3)):"fetch"==this.submitType?fetch(this.actionUrl,{method:this.submitMethod,headers:"json"===this.submitDataFormat?{"Content-Type":"application/json",...this.requestHeaders}:{...this.requestHeaders},body:"json"===this.submitDataFormat?JSON.stringify(this.serializeData()):this.serializeData(!0)}).then((e=>{200===e.status||201===e.status?(this.resetOnSuccess&&this.reset(),"function"==typeof this.onSuccess&&this.onSuccess(e)):"function"==typeof this.onError&&this.onError(e)})).catch((e=>{"function"==typeof this.onError&&this.onError(e)})).finally((()=>{this.submittingForm(!1)})):this.form.submit();else{if(this.submittingForm(!1),"function"==typeof this.onValidationError&&this.onValidationError(e),this.debug&&this.showLog(`this fields have failed validation: ${e.toString().replace(/,/g,", ")}.`),this.scrollOnError){const e=this.form.querySelector(`.form__field.${this.classes.fieldHasError}`);(e=>{const t=e.getBoundingClientRect();return t.top>=0&&t.left>=0&&t.bottom<=(window.innerHeight||document.documentElement.clientHeight)&&t.right<=(window.innerWidth||document.documentElement.clientWidth)})(e)||e.scrollIntoView({behavior:"smooth"})}this.debug&&this.showLog("there are invalid fields.")}}submittingForm(e){let t=document.getElementsByTagName("body").item(0);e?(this.form.classList.add(this.classes.formSubmittingState),this.submitBtn.classList.add(this.classes.buttonSubmittingState),t.classList.add("--block"),"function"==typeof this.onSubmitStart&&this.onSubmitStart()):(this.form.classList.remove(this.classes.formSubmittingState),this.submitBtn.classList.remove(this.classes.buttonSubmittingState),t.classList.remove("--block"),"function"==typeof this.onSubmitEnd&&this.onSubmitEnd())}serializeData(e=!1){const t=new FormData(this.form),i={};for(const e of t)if(!this.serializerIgnoreList.includes(e[0])){if(e[1]instanceof File&&!e[1].size&&!e[1].name)continue;i[e[0]]=e[1]}if(this.fieldGroups)for(const e in this.fieldGroups)if(Object.hasOwnProperty.call(this.fieldGroups,e)){let s=[{}];for(const r of this.fieldGroups[e])s[0][r]=t.get(r),delete i[r];i[e]=s}return e?t:i}reset(){this.form.reset(),this.form.querySelectorAll(".form__field").forEach((e=>e.classList.remove("--filled",`${this.classes.fieldHasError}`))),this.form.querySelectorAll(".form__control").forEach((e=>e.setAttribute("aria-invalid","false"))),this.currentStep&&this.changeStep(1)}changeStep(t){if(!this.stepChanging){const i=this.currentStepOptional?this.currentStep+"b":this.currentStep,s=this.form.querySelector('[data-step="'+i+'"]'),r=s.querySelectorAll(`.${this.classes.requiredField}`),a="next"===t?this.currentStep+1:"prev"!==t||this.currentStepOptional?"optional"===t?this.currentStep+"b":this.currentStep:this.currentStep-1,o=this.form.querySelector('[data-step="'+a+'"]');(this.currentStep!==a||this.currentStepOptional)&&(this.stepChanging=!0,this.isValid=!0,setTimeout((()=>{!r||"next"!==t&&"optional"!==t||r.forEach((e=>{this.validator.validateField(e)||(this.isValid=!1)})),s&&o&&this.isValid?e({element:s,enter:!1,time:200,displayType:"flex",callback:()=>{s.classList.remove("--active"),e({element:o,enter:!0,time:200,displayType:"flex",callback:()=>{o.classList.add("--active"),this.stepChanging=!1,this.currentStepOptional="optional"===t,this.currentStep=parseInt(a),"function"==typeof this.onStepChange&&this.onStepChange(i,a)}})}}):this.stepChanging=!1}),50))}}nextStep(){this.changeStep("next")}optionalStep(){this.changeStep("optional")}prevStep(){this.changeStep("prev")}isControlFilled(e){let t=e.parentElement;""!==e.value?t.classList.add("--filled"):t.classList.remove("--filled")}filterNumber(e,t=[]){const i=t.join(""),s=new RegExp("[^"+i+"0-9]","g");return e.toString().replace(s,"")}filterFormattedQuantity(e,t=".",i=",",s){const r=i?e.toString().split(i):[e],a=r[0].replace(/\B(?=(\d{3})+(?!\d))/g,t);let o="";return o=s>0&&r[1]&&r[1].length?a+i+r[1].slice(0,s):a,o}filterMoneyAmount(e,t="$",i=".",s=",",r){if(!e||e==t)return"";let a=this.filterNumber(e,[s||""]);return a=this.filterFormattedQuantity(a,i,s,r),`${t} ${a}`}filterPhoneNumber(e){return e.replace(/[^\d+\-() ]*/g,"")}togglePasswordVisibility(e){this.debug&&this.showLog("Password visibility toggled!");const t=e.parentElement.querySelector(".form__control");if(t){const i="password"===t.getAttribute("type")?"text":"password";t.setAttribute("type",i),e.classList.toggle("--hide")}}declareHandlers(){const e=this;if(!this.submitBtn)throw new Error(`There's no submit button in this form "${this.form.id}".`);this.submitBtn.addEventListener("click",(function(t){t.preventDefault(),"function"==typeof e.onBeforeSubmit&&e.onBeforeSubmit(),e.submit()})),this.validator.realTimeValidations(this.form),e.form.querySelectorAll(`.form__field.${e.classes.validateOnBlur}`).forEach((e=>{console.log("ONBLUR",e),e.querySelector(".form__control").addEventListener("blur",(()=>{this.validator.validateField(e)||(this.isValid=!1)}))})),this.form.querySelectorAll(".form__next-step").forEach((t=>{t.addEventListener("click",e.nextStep.bind(e))})),this.form.querySelectorAll(".form__optional-step").forEach((t=>{t.addEventListener("click",e.optionalStep.bind(e))})),this.form.querySelectorAll(".form__prev-step").forEach((t=>{t.addEventListener("click",e.prevStep.bind(e))})),this.form.querySelectorAll(".form__control").forEach((e=>{this.isControlFilled(e),e.addEventListener("keyup",(()=>{this.isControlFilled(e)})),e.addEventListener("change",(()=>{this.isControlFilled(e)}))})),this.form.querySelectorAll(".form__control").forEach((e=>{e.addEventListener("focus",(()=>{this.validator.clearControlError(e)}))})),this.form.querySelectorAll("."+this.classes.clearFieldError).forEach((i=>{i.addEventListener("click",(()=>{const s=t({element:i,className:"form__field"});e.validator.clearControlError(s.querySelector(".form__control"))}))})),this.form.querySelectorAll(".form__field.--number input").forEach((e=>{const i=this,s=t({element:e,className:"form__field"}),r=s&&s.dataset.thousandsSeparator?s.dataset.thousandsSeparator:null,a=s&&s.dataset.decimalSeparator?s.dataset.decimalSeparator:"",o=s&&s.dataset.decimals?s.dataset.decimals:"";function l(){e.value=i.filterNumber(e.value,[a])}e.addEventListener("focus",l),e.addEventListener("input",l),e.addEventListener("paste",l),e.addEventListener("blur",(()=>{e.value=r?i.filterFormattedQuantity(e.value,r,a,parseInt(o)):i.filterNumber(e.value)}))})),this.form.querySelectorAll(".form__field.--money-amount input").forEach((e=>{const i=this,s=t({element:e,className:"form__field"}),r=s&&s.dataset.currency?s.dataset.currency:"$",a=s&&s.dataset.thousandsSeparator?s.dataset.thousandsSeparator:".",o=s&&s.dataset.decimalSeparator?s.dataset.decimalSeparator:"",l=s&&s.dataset.decimals?s.dataset.decimals:"";function n(){e.value=i.filterNumber(e.value,[o])}e.addEventListener("focus",n),e.addEventListener("input",n),e.addEventListener("paste",n),e.addEventListener("blur",(()=>{e.value=this.filterMoneyAmount(e.value,r,a,o,parseInt(l))}))})),this.form.querySelectorAll(".form__field.--phone input").forEach((e=>{e.addEventListener("input",(()=>{e.value=this.filterPhoneNumber(e.value)})),e.addEventListener("paste",(()=>{e.value=this.filterPhoneNumber(e.value)}))})),this.form.querySelectorAll(".form__toggle-password-visibility").forEach((e=>{e.addEventListener("click",this.togglePasswordVisibility(e))}))}showLog(e,t="log"){"log"==t?console.log("::EgoForm:: "+e):"data"==t&&(console.log("::EgoForm:: DATA"),console.table(e))}}}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@egodesign/form",
3
- "version": "1.3.0",
3
+ "version": "1.4.1",
4
4
  "description": "JS Form component",
5
5
  "module": "dist/js/egodesign.form.esm.min.js",
6
6
  "browser": "dist/js/egodesign.form.umd.min.js",