@egodesign/form 1.0.1 → 1.0.5
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
|
@@ -1,2 +1,127 @@
|
|
|
1
|
-
# egodesign
|
|
2
|
-
|
|
1
|
+
# @egodesign/form
|
|
2
|
+
A lightweight Javascript component to fully validate and send forms.
|
|
3
|
+
</br></br>
|
|
4
|
+
|
|
5
|
+
## Usage:
|
|
6
|
+
Import the **`EgoForm`** class into your file and then create as many instances as needed.
|
|
7
|
+
```js
|
|
8
|
+
import EgoForm from '@egodesign/form';
|
|
9
|
+
|
|
10
|
+
const myForm = new EgoForm({
|
|
11
|
+
element: document.getElementById('myForm'),
|
|
12
|
+
submitType: 'fetch',
|
|
13
|
+
debug: true,
|
|
14
|
+
onSuccess: resp => console.log('Success', resp),
|
|
15
|
+
onError: err => console.log('Error', err)
|
|
16
|
+
});
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## HTML structure sample:
|
|
20
|
+
```html
|
|
21
|
+
<form method="GET" action="https://jsonplaceholder.typicode.com/todos/1" id="myForm" novalidate>
|
|
22
|
+
<div class="form__field --required" data-type="text">
|
|
23
|
+
<label for="nameInput">Name</label>
|
|
24
|
+
<input class="form__control"
|
|
25
|
+
type="text"
|
|
26
|
+
name="name"
|
|
27
|
+
id="nameInput"
|
|
28
|
+
placeholder="Text input"
|
|
29
|
+
aria-invalid="false"
|
|
30
|
+
aria-errormessage="nameInputError"
|
|
31
|
+
required>
|
|
32
|
+
<p class="form__error" id="nameInputError"></p>
|
|
33
|
+
</div>
|
|
34
|
+
|
|
35
|
+
<div class="form__field --required" data-type="email">
|
|
36
|
+
<label for="emailInput">Email</label>
|
|
37
|
+
<input class="form__control"
|
|
38
|
+
type="email"
|
|
39
|
+
name="email"
|
|
40
|
+
id="emailInput"
|
|
41
|
+
placeholder="Email input"
|
|
42
|
+
aria-invalid="false"
|
|
43
|
+
aria-errormessage="emailInputError"
|
|
44
|
+
required>
|
|
45
|
+
<p class="form__error" id="emailInputError"></p>
|
|
46
|
+
</div>
|
|
47
|
+
|
|
48
|
+
<div class="form__field" data-type="file" data-max-size="15">
|
|
49
|
+
<label for="fileInput">File upload</label>
|
|
50
|
+
<small>Max. file size 2MB</small>
|
|
51
|
+
<input class="file-input form__control"
|
|
52
|
+
type="file"
|
|
53
|
+
name="resume"
|
|
54
|
+
id="fileInput"
|
|
55
|
+
aria-invalid="false"
|
|
56
|
+
aria-errormessage="fileInputError">
|
|
57
|
+
<p class="form__error" id="fileInputError"></p>
|
|
58
|
+
</div>
|
|
59
|
+
|
|
60
|
+
<div class="form__field" data-type="text">
|
|
61
|
+
<label>Message</label>
|
|
62
|
+
<textarea class="form__control"
|
|
63
|
+
name="message"
|
|
64
|
+
placeholder="Textarea"
|
|
65
|
+
aria-errormessage="msgTextError">
|
|
66
|
+
</textarea>
|
|
67
|
+
<p class="form__error" id="msgTextError"></p>
|
|
68
|
+
</div>
|
|
69
|
+
|
|
70
|
+
<button type="submit">Submit</button>
|
|
71
|
+
</form>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Required Classes
|
|
75
|
+
| Class | Description |
|
|
76
|
+
| --- | ----------- |
|
|
77
|
+
| `form__field` | This is the element that wraps the label, the control and the error message of a specific field. |
|
|
78
|
+
| `form__control` | This is a control element. It could be either an input, a select, a textarea, etc. |
|
|
79
|
+
| `form__error` | This is the element which will be used to display error messages for a specific field. |
|
|
80
|
+
<br>
|
|
81
|
+
|
|
82
|
+
### Customizable Classes
|
|
83
|
+
| Name | Default | Description |
|
|
84
|
+
| --- | --- | ----------- |
|
|
85
|
+
| *requiredField* | `--required` | Use this class to mark required fields. |
|
|
86
|
+
| *requiredIfFilledField* | `--required-if-filled` | Use this class to mark those fields that should be validated only when filled. For example, an email field that is not required but should be a valid email if filled. |
|
|
87
|
+
| *fieldHasError* | `--has-error` | This class is added to the fields that has errors after validation and removed when the field is focused. |
|
|
88
|
+
| *controlHasError* | - | You can set this class to be added to the controls that has errors. Works similar to *fieldHasError*. |
|
|
89
|
+
| *hiddenErrorMessage* | `--hidden` | This class is removed from the error messages when it's parent field has errors and added back when the field is focused. |
|
|
90
|
+
| *formSubmittingState* | `--submitting` | This class is added to the form while it's being submited. |
|
|
91
|
+
| *buttonSubmittingState* | `--loading` | This class is added to the submit button while the form is being submited. |
|
|
92
|
+
<br>
|
|
93
|
+
|
|
94
|
+
### Options
|
|
95
|
+
| Name | Description | Accepted values |
|
|
96
|
+
| --- | ----------- | ----------- |
|
|
97
|
+
| *element* | The form element. I.g. `document.getElementById('myform')` | A DOM element
|
|
98
|
+
| *submitType* | The method that will be used to submit the form. **IMPORTANT**: the action attribute is required in any case. | `fetch`, `get` and `post`
|
|
99
|
+
| *submitDataFormat* | If submitTypes is fetch, this option will be use to define de content type of the request. | `json` and `formData`
|
|
100
|
+
| *requestHeaders* | If submitTypes is fetch, this option lets you pass your own headers. Should recieve an object containing valid HTTP headers. See [reference](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers). | Object or `null`.
|
|
101
|
+
| *fieldGroups* | Group fields as nestes objects inside the body of the request. Should recieve an object containing key-value pairs, where the key is the name of the group and the value an array listing the field names. | Object or `null`.
|
|
102
|
+
| *classes* | Customize some classes to match your own. Should recieve an object containig the replaced classnames. See [customizable classes] | Object or `null`.
|
|
103
|
+
| *customValidations* | Define your own validations. Should recieve an object containig key-value pairs, where the key is the name of the custom `data-type`, and the value an array of validations defining a condition to be passed and a message in case it's not. | Object or `null`.
|
|
104
|
+
| *resetOnSuccess* | This option completely resets the form and its fields. | Boolean, default `true`.
|
|
105
|
+
| *scrollOnError* | This option smoothly scrolls the page to show the first field with errors. Useful when building long forms to make sure the user sees the errors. | Boolean, default `true`.
|
|
106
|
+
| *debug* | On debug mode, the form won't be submitted. Intead, every step will be logged into the dev console of the browser. | Boolean, default `false`.
|
|
107
|
+
<br>
|
|
108
|
+
|
|
109
|
+
### Events
|
|
110
|
+
| Name | Description | Accepted values |
|
|
111
|
+
| --- | ----------- | ----------- |
|
|
112
|
+
| *onSubmitStart* | Event triggered when the submit starts. | An anonymous function or `null`.
|
|
113
|
+
| *onSubmitEnd* | Event triggered when the submit ends, regardless of the outcome. | An anonymous function or `null`.
|
|
114
|
+
| *onSuccess* | Event triggered when the request results successful. | An anonymous function or `null`.
|
|
115
|
+
| *onError* | Event triggered when the response returns an error. | An anonymous function or `null`.
|
|
116
|
+
<br>
|
|
117
|
+
|
|
118
|
+
### Validation:
|
|
119
|
+
In order to use validations, you must set the correct data type for each field. You can do so by adding a `type` data attribute to the field element, e.g; `<div class="form__field" data-type="text">`. This attribute will be used by the validator to run certain tests. Here's a list of the different available data types:
|
|
120
|
+
| Name | Description | Extra attributes |
|
|
121
|
+
| ---| --- | ----------- |
|
|
122
|
+
| `text` | This can be considered as the default type. It's use for simple text input and it doesn't have any special validation appart from the required ones. | |
|
|
123
|
+
| `email` | Used for email inputs. It validates the value to comply the requirement for a well formed email address. | |
|
|
124
|
+
| `url` | Used for URL inputs. It validates the value to comply the requirement for a well formed URL. | |
|
|
125
|
+
| `cuit`/`cuil` | It validates the value to comply the requirement for a valid CUIT or CUIL number, applying the official formula. | |
|
|
126
|
+
| `money` | It validates the value to comply the requirement for a valid CUIT or CUIL number, applying the official formula. | |
|
|
127
|
+
|
|
@@ -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={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 i{constructor({customValidations:e,classes:i,customValidationMessages:s}){this.customValidations=e,this.validationMessages=s||t,this.classes=i}validateField(e){const t=e.dataset.type;e.classList.contains(this.classes.requiredField);const i=e.classList.contains(this.classes.requiredIfFilledField),s=e.querySelector(".form__error"),r=["radio","checkbox"].includes(t)?e.querySelector(".form__control:checked"):e.querySelector(".form__control"),a=r?r.getAttribute("name"):"",o=Object.keys(this.customValidations);if(r||this.throwError("control not found."),a||this.throwError("control name not found."),r.value){if(r.value){switch(t){case"email":if(!this.isValidEmail(r.value))return s&&(s.innerText=this.validationMessages.email.invalid),this.displayFieldError(r,e,s),!1;break;case"password_repeat":{const t=document.getElementById("password");if(t&&r.value!=t.value)return s&&(s.innerText=this.validationMessages.password_repeat.unequal),this.displayFieldError(r,e,s),!1;break}case"cuil":case"cuit":if(!this.isValidCuitCuil(r.value))return s&&(s.innerText=this.validationMessages.cuil.invalid),this.displayFieldError(r,e,s),!1;break;case"url":if(!this.isValidUrl(r.value))return s&&(s.innerText=this.validationMessages.url.invalid),this.displayFieldError(r,e,s),!1;break;case"money":const t=r.dataset.currency?r.dataset.currency:"$";if(""==r.value||r.value==t)return s&&(s.innerText=this.validationMessages.default.empty),this.displayFieldError(r,e,s),!1;break;case"single-checkbox":if(!r.checked)return this.displayFieldError(r,e,s),s&&(s.innerText=this.validationMessages[a]?this.validationMessages[a].empty:this.validationMessages.default.empty),!1}for(const i of o)if(t===i)for(const i of this.customValidations[t])if(!i.condition(r.value))return s&&(s.innerText=i.message||""),this.displayFieldError(r,e,s),!1}}else if(!i)return this.displayFieldError(r,e,s),s&&(s.innerText=this.validationMessages[a]?this.validationMessages[a].empty:this.validationMessages.default.empty),!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("--has-error")):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 t=(({element:e,className:t})=>{if(!e)return!1;for(;e&&!e.classList.contains(t);)e=!!e.parentElement&&e.parentElement;return e})({element:e,className:"form__field"}),i=t.querySelector(".form__error");t.classList.remove(this.classes.fieldHasError),i&&(i.innerText="",i.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:s,submitDataFormat:r,requestHeaders:a,fieldGroups:o,serializerIgnoreList:l,customValidations:n,customValidationMessages:u,onSubmitStart:d,onSubmitEnd:c,onSuccess:h,onError:m,resetOnSuccess:f,debug:p}){this.form=e,this.submitType=s||"fetch",this.submitDataFormat=r||"fromData",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",...t},this.isValid=!0,this.validator=new i({customValidations:n||{},classes:this.classes,customValidationMessages:u||null}),this.onSubmitStart=d||!1,this.onSubmitEnd=c||!1,this.onSuccess=h||!1,this.onError=m||!1,this.fieldGroups=o||!1,this.hasFile=!1,this.serializerIgnoreList=l||[],this.resetOnSuccess=f||!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.debug=p||!1,this.declareHandlers(),this.debug&&this.showLog("initialized!")}submit(){if(this.debug&&this.showLog(`submitting using ${this.submitType}!`),this.submittingForm(!0),this.isValid=!0,this.form.querySelectorAll(`.${this.classes.requiredField}, .${this.classes.requiredIfFilledField}`).forEach((e=>{this.validator.validateField(e)||(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:{"Content-type":"json"===this.submitDataFormat?"application/json":"multipart/form-data",...this.requestHeaders},body:"json"===this.submitDataFormat?JSON.stringify(this.serializeData()):this.serializeData()}).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{this.submittingForm(!1);const e=this.form.querySelector(".form__field.--has-error");(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","--has-error"))),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.isValid&&(this.isValid=this.validator.validateField(e))})),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)}})}}):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){return e.replace(/[^0-9]/g,"")}filterMoneyAmount(e,t="$"){if(!e||e==t)return"";return`${t} ${this.filterNumber(e).toString().replace(/\B(?=(\d{3})+(?!\d))/g,".")}`}filterPhoneNumber(e){return e.replace(/[a-zA-Z*'";:\\/?!@#$%^&=_`~]/g,"")}togglePasswordVisibility(e){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(),e.submit()})),this.validator.realTimeValidations(this.form),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(".form__field.--number input").forEach((e=>{e.addEventListener("input",(()=>{e.value=this.filterNumber(e.value)})),e.addEventListener("paste",(()=>{e.value=this.filterNumber(e.value)}))})),this.form.querySelectorAll(".form__field.--money-amount input").forEach((e=>{const t=e.dataset.currency?e.dataset.currency:"$";e.addEventListener("input",(()=>{e.value=this.filterMoneyAmount(e.value,t)})),e.addEventListener("paste",(()=>{e.value=this.filterMoneyAmount(e.value,t)}))})),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:s,displayType:i,callback:r})=>{e.style.opacity=t?0:1,t&&(e.style.display=i||"block");let a=+new Date;!function i(){e.style.opacity=t?+e.style.opacity+(new Date-a)/(s||200):+e.style.opacity-(new Date-a)/(s||200),a=+new Date,t&&+e.style.opacity<1||!t&&+e.style.opacity>0?window.requestAnimationFrame&&requestAnimationFrame(i)||setTimeout(i,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},s={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 i{constructor({customValidations:e,classes:t,customValidationMessages:i}){this.customValidations=e,this.validationMessages=i||s,this.classes=t}validateField(e){const t=e.dataset.type,s=["radio","checkbox"].includes(t),i=e.classList.contains(this.classes.requiredIfFilledField),r=e.querySelector(".form__error"),a=e.querySelector(".form__control"),o=s?e.querySelector(".form__control:checked"):null,l=a?a.getAttribute("name"):"",n=Object.keys(this.customValidations);if("name"==l&&console.log(s,o,a.value),a||this.throwError("control not found."),l||this.throwError("control name not found."),s&&!o||!a.value){if(!i)return this.displayFieldError(a,e,r),r&&(r.innerText=this.validationMessages[l]?this.validationMessages[l].empty:this.validationMessages.default.empty),!1}else if(a.value){switch(t){case"email":if(!this.isValidEmail(a.value))return r&&(r.innerText=this.validationMessages.email.invalid),this.displayFieldError(a,e,r),!1;break;case"password_repeat":{const t=document.getElementById("password");if(t&&a.value!=t.value)return r&&(r.innerText=this.validationMessages.password_repeat.unequal),this.displayFieldError(a,e,r),!1;break}case"cuil":case"cuit":if(!this.isValidCuitCuil(a.value))return r&&(r.innerText=this.validationMessages.cuil.invalid),this.displayFieldError(a,e,r),!1;break;case"url":if(!this.isValidUrl(a.value))return r&&(r.innerText=this.validationMessages.url.invalid),this.displayFieldError(a,e,r),!1;break;case"money":const t=a.dataset.currency?a.dataset.currency:"$";if(""==a.value||a.value==t)return r&&(r.innerText=this.validationMessages.default.empty),this.displayFieldError(a,e,r),!1;break;case"single-checkbox":if(!a.checked)return this.displayFieldError(a,e,r),r&&(r.innerText=this.validationMessages[l]?this.validationMessages[l].empty:this.validationMessages.default.empty),!1}for(const s of n)if(t===s)for(const s of this.customValidations[t])if(!s.condition(a.value))return r&&(r.innerText=s.message||""),this.displayFieldError(a,e,r),!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 s=e.toString().split("");if(11!=s.length)return!1;s=s.map((e=>parseInt(e)));const i=parseInt(s.pop());let r=11-s.reduce(((e,s,i)=>e+s*t[i]),0)%11;return 10==r&&(r=9),11==r&&(r=0),r==i}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 s=e.querySelector(".form__control"),i=parseFloat(e.dataset.minSize),r=parseFloat(e.dataset.maxSize),a=e.querySelector(".form__error"),o=s.files[0].name,l=s.files[0].size,n=parseFloat(s.files.length?(l/1048576).toFixed(1):0);n>r||!l?(s.value="",e.classList.remove("--has-file"),s.setAttribute("aria-invalid","true"),e.classList.add("--has-error")):o?(this.hasFile=!0,e.classList.add("--has-file")):(this.hasFile=!1,e.classList.remove("--has-file")),l?n<i?t=this.validationMessages.file.min_size.replace("[[var]]",i+" MB"):n>r&&(t=this.validationMessages.file.max_size.replace("[[var]]",r+" MB")):t=this.validationMessages.file.empty,t&&(a.innerText=t,this.displayFieldError(s,e,a))}displayFieldError(e,t,s){e.setAttribute("aria-invalid","true"),t.classList.add(this.classes.fieldHasError),this.classes.controlHasError&&e.classList.add(this.classes.controlHasError),s&&s.classList.remove(this.classes.hiddenErrorMessage)}clearControlError(e){e.setAttribute("aria-invalid","false"),this.classes.controlHasError&&e.classList.remove(this.classes.controlHasError);const s=t({element:e,className:"form__field"}),i=s.querySelector(".form__error");s.classList.remove(this.classes.fieldHasError),i&&(i.innerText="",i.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:s,submitDataFormat:r,requestHeaders:a,fieldGroups:o,serializerIgnoreList:l,customValidations:n,customValidationMessages:u,onStepChange:d,onSubmitStart:c,onSubmitEnd:h,onSuccess:m,onError:f,resetOnSuccess:p,scrollOnError:F,debug:g}){this.form=e,this.submitType=s||"fetch",this.submitDataFormat=r||"fromData",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",...t},this.isValid=!0,this.validator=new i({customValidations:n||{},classes:this.classes,customValidationMessages:u||null}),this.onStepChange=d||!1,this.onSubmitStart=c||!1,this.onSubmitEnd=h||!1,this.onSuccess=m||!1,this.onError=f||!1,this.fieldGroups=o||!1,this.hasFile=!1,this.serializerIgnoreList=l||[],this.resetOnSuccess=p||!0,this.scrollOnError=F||!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.debug=g||!1,this.declareHandlers(),this.debug&&this.showLog("initialized!")}submit(){if(this.debug&&this.showLog(`submitting using ${this.submitType}!`),this.submittingForm(!0),this.isValid=!0,this.form.querySelectorAll(`.${this.classes.requiredField}, .${this.classes.requiredIfFilledField}`).forEach((e=>{this.validator.validateField(e)||(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:{"Content-type":"json"===this.submitDataFormat?"application/json":"multipart/form-data",...this.requestHeaders},body:"json"===this.submitDataFormat?JSON.stringify(this.serializeData()):this.serializeData()}).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),this.scrollOnError){const e=this.form.querySelector(".form__field.--has-error");(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),s={};for(const e of t)if(!this.serializerIgnoreList.includes(e[0])){if(e[1]instanceof File&&!e[1].size&&!e[1].name)continue;s[e[0]]=e[1]}if(this.fieldGroups)for(const e in this.fieldGroups)if(Object.hasOwnProperty.call(this.fieldGroups,e)){let i=[{}];for(const r of this.fieldGroups[e])i[0][r]=t.get(r),delete s[r];s[e]=i}return e?t:s}reset(){this.form.reset(),this.form.querySelectorAll(".form__field").forEach((e=>e.classList.remove("--filled","--has-error"))),this.form.querySelectorAll(".form__control").forEach((e=>e.setAttribute("aria-invalid","false"))),this.currentStep&&this.changeStep(1)}changeStep(t){if(!this.stepChanging){const s=this.currentStepOptional?this.currentStep+"b":this.currentStep,i=this.form.querySelector('[data-step="'+s+'"]'),r=i.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.isValid&&(this.isValid=this.validator.validateField(e))})),i&&o&&this.isValid?e({element:i,enter:!1,time:200,displayType:"flex",callback:()=>{i.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(s,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 s=t.join(""),i=new RegExp("[^"+s+"0-9]","g");return e.toString().replace(i,"")}filterFormattedQuantity(e,t=".",s=",",i){const r=s?e.toString().split(s):[e],a=r[0].replace(/\B(?=(\d{3})+(?!\d))/g,t);let o="";return o=i>0&&r[1]&&r[1].length?a+s+r[1].slice(0,i):a,o}filterMoneyAmount(e,t="$",s=".",i=",",r){if(!e||e==t)return"";let a=this.filterNumber(e,[i||""]);return a=this.filterFormattedQuantity(a,s,i,r),`${t} ${a}`}filterPhoneNumber(e){return e.replace(/[a-zA-Z*'";:\\/?!@#$%^&=_`~]/g,"")}togglePasswordVisibility(e){const t=e.parentElement.querySelector(".form__control");if(t){const s="password"===t.getAttribute("type")?"text":"password";t.setAttribute("type",s),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(),e.submit()})),this.validator.realTimeValidations(this.form),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(".form__field.--number input").forEach((e=>{const s=this,i=t({element:e,className:"form__field"}),r=i&&i.dataset.thousandsSeparator?i.dataset.thousandsSeparator:null,a=i&&i.dataset.decimalSeparator?i.dataset.decimalSeparator:"",o=i&&i.dataset.decimals?i.dataset.decimals:"";function l(){e.value=s.filterNumber(e.value,[a])}e.addEventListener("focus",l),e.addEventListener("input",l),e.addEventListener("paste",l),e.addEventListener("blur",(()=>{e.value=r?s.filterFormattedQuantity(e.value,r,a,parseInt(o)):s.filterNumber(e.value)}))})),this.form.querySelectorAll(".form__field.--money-amount input").forEach((e=>{const s=this,i=t({element:e,className:"form__field"}),r=i&&i.dataset.currency?i.dataset.currency:"$",a=i&&i.dataset.thousandsSeparator?i.dataset.thousandsSeparator:".",o=i&&i.dataset.decimalSeparator?i.dataset.decimalSeparator:"",l=i&&i.dataset.decimals?i.dataset.decimals:"";function n(){e.value=s.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={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 i{constructor({customValidations:e,classes:i,customValidationMessages:s}){this.customValidations=e,this.validationMessages=s||t,this.classes=i}validateField(e){const t=e.dataset.type;e.classList.contains(this.classes.requiredField);const i=e.classList.contains(this.classes.requiredIfFilledField),s=e.querySelector(".form__error"),r=["radio","checkbox"].includes(t)?e.querySelector(".form__control:checked"):e.querySelector(".form__control"),a=r?r.getAttribute("name"):"",o=Object.keys(this.customValidations);if(r||this.throwError("control not found."),a||this.throwError("control name not found."),r.value){if(r.value){switch(t){case"email":if(!this.isValidEmail(r.value))return s&&(s.innerText=this.validationMessages.email.invalid),this.displayFieldError(r,e,s),!1;break;case"password_repeat":{const t=document.getElementById("password");if(t&&r.value!=t.value)return s&&(s.innerText=this.validationMessages.password_repeat.unequal),this.displayFieldError(r,e,s),!1;break}case"cuil":case"cuit":if(!this.isValidCuitCuil(r.value))return s&&(s.innerText=this.validationMessages.cuil.invalid),this.displayFieldError(r,e,s),!1;break;case"url":if(!this.isValidUrl(r.value))return s&&(s.innerText=this.validationMessages.url.invalid),this.displayFieldError(r,e,s),!1;break;case"money":const t=r.dataset.currency?r.dataset.currency:"$";if(""==r.value||r.value==t)return s&&(s.innerText=this.validationMessages.default.empty),this.displayFieldError(r,e,s),!1;break;case"single-checkbox":if(!r.checked)return this.displayFieldError(r,e,s),s&&(s.innerText=this.validationMessages[a]?this.validationMessages[a].empty:this.validationMessages.default.empty),!1}for(const i of o)if(t===i)for(const i of this.customValidations[t])if(!i.condition(r.value))return s&&(s.innerText=i.message||""),this.displayFieldError(r,e,s),!1}}else if(!i)return this.displayFieldError(r,e,s),s&&(s.innerText=this.validationMessages[a]?this.validationMessages[a].empty:this.validationMessages.default.empty),!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("--has-error")):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 t=(({element:e,className:t})=>{if(!e)return!1;for(;e&&!e.classList.contains(t);)e=!!e.parentElement&&e.parentElement;return e})({element:e,className:"form__field"}),i=t.querySelector(".form__error");t.classList.remove(this.classes.fieldHasError),i&&(i.innerText="",i.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 s{constructor({element:e,classes:t,submitType:s,submitDataFormat:r,requestHeaders:a,fieldGroups:o,serializerIgnoreList:l,customValidations:n,customValidationMessages:u,onSubmitStart:d,onSubmitEnd:c,onSuccess:h,onError:m,resetOnSuccess:f,debug:p}){this.form=e,this.submitType=s||"fetch",this.submitDataFormat=r||"fromData",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",...t},this.isValid=!0,this.validator=new i({customValidations:n||{},classes:this.classes,customValidationMessages:u||null}),this.onSubmitStart=d||!1,this.onSubmitEnd=c||!1,this.onSuccess=h||!1,this.onError=m||!1,this.fieldGroups=o||!1,this.hasFile=!1,this.serializerIgnoreList=l||[],this.resetOnSuccess=f||!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.debug=p||!1,this.declareHandlers(),this.debug&&this.showLog("initialized!")}submit(){if(this.debug&&this.showLog(`submitting using ${this.submitType}!`),this.submittingForm(!0),this.isValid=!0,this.form.querySelectorAll(`.${this.classes.requiredField}, .${this.classes.requiredIfFilledField}`).forEach((e=>{this.validator.validateField(e)||(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:{"Content-type":"json"===this.submitDataFormat?"application/json":"multipart/form-data",...this.requestHeaders},body:"json"===this.submitDataFormat?JSON.stringify(this.serializeData()):this.serializeData()}).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{this.submittingForm(!1);const e=this.form.querySelector(".form__field.--has-error");(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","--has-error"))),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.isValid&&(this.isValid=this.validator.validateField(e))})),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)}})}}):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){return e.replace(/[^0-9]/g,"")}filterMoneyAmount(e,t="$"){if(!e||e==t)return"";return`${t} ${this.filterNumber(e).toString().replace(/\B(?=(\d{3})+(?!\d))/g,".")}`}filterPhoneNumber(e){return e.replace(/[a-zA-Z*'";:\\/?!@#$%^&=_`~]/g,"")}togglePasswordVisibility(e){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(),e.submit()})),this.validator.realTimeValidations(this.form),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(".form__field.--number input").forEach((e=>{e.addEventListener("input",(()=>{e.value=this.filterNumber(e.value)})),e.addEventListener("paste",(()=>{e.value=this.filterNumber(e.value)}))})),this.form.querySelectorAll(".form__field.--money-amount input").forEach((e=>{const t=e.dataset.currency?e.dataset.currency:"$";e.addEventListener("input",(()=>{e.value=this.filterMoneyAmount(e.value,t)})),e.addEventListener("paste",(()=>{e.value=this.filterMoneyAmount(e.value,t)}))})),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{s as default};
|
|
1
|
+
const e=({element:e,enter:t,time:s,displayType:i,callback:r})=>{e.style.opacity=t?0:1,t&&(e.style.display=i||"block");let a=+new Date;!function i(){e.style.opacity=t?+e.style.opacity+(new Date-a)/(s||200):+e.style.opacity-(new Date-a)/(s||200),a=+new Date,t&&+e.style.opacity<1||!t&&+e.style.opacity>0?window.requestAnimationFrame&&requestAnimationFrame(i)||setTimeout(i,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},s={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 i{constructor({customValidations:e,classes:t,customValidationMessages:i}){this.customValidations=e,this.validationMessages=i||s,this.classes=t}validateField(e){const t=e.dataset.type,s=["radio","checkbox"].includes(t),i=e.classList.contains(this.classes.requiredIfFilledField),r=e.querySelector(".form__error"),a=e.querySelector(".form__control"),o=s?e.querySelector(".form__control:checked"):null,l=a?a.getAttribute("name"):"",n=Object.keys(this.customValidations);if("name"==l&&console.log(s,o,a.value),a||this.throwError("control not found."),l||this.throwError("control name not found."),s&&!o||!a.value){if(!i)return this.displayFieldError(a,e,r),r&&(r.innerText=this.validationMessages[l]?this.validationMessages[l].empty:this.validationMessages.default.empty),!1}else if(a.value){switch(t){case"email":if(!this.isValidEmail(a.value))return r&&(r.innerText=this.validationMessages.email.invalid),this.displayFieldError(a,e,r),!1;break;case"password_repeat":{const t=document.getElementById("password");if(t&&a.value!=t.value)return r&&(r.innerText=this.validationMessages.password_repeat.unequal),this.displayFieldError(a,e,r),!1;break}case"cuil":case"cuit":if(!this.isValidCuitCuil(a.value))return r&&(r.innerText=this.validationMessages.cuil.invalid),this.displayFieldError(a,e,r),!1;break;case"url":if(!this.isValidUrl(a.value))return r&&(r.innerText=this.validationMessages.url.invalid),this.displayFieldError(a,e,r),!1;break;case"money":const t=a.dataset.currency?a.dataset.currency:"$";if(""==a.value||a.value==t)return r&&(r.innerText=this.validationMessages.default.empty),this.displayFieldError(a,e,r),!1;break;case"single-checkbox":if(!a.checked)return this.displayFieldError(a,e,r),r&&(r.innerText=this.validationMessages[l]?this.validationMessages[l].empty:this.validationMessages.default.empty),!1}for(const s of n)if(t===s)for(const s of this.customValidations[t])if(!s.condition(a.value))return r&&(r.innerText=s.message||""),this.displayFieldError(a,e,r),!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 s=e.toString().split("");if(11!=s.length)return!1;s=s.map((e=>parseInt(e)));const i=parseInt(s.pop());let r=11-s.reduce(((e,s,i)=>e+s*t[i]),0)%11;return 10==r&&(r=9),11==r&&(r=0),r==i}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 s=e.querySelector(".form__control"),i=parseFloat(e.dataset.minSize),r=parseFloat(e.dataset.maxSize),a=e.querySelector(".form__error"),o=s.files[0].name,l=s.files[0].size,n=parseFloat(s.files.length?(l/1048576).toFixed(1):0);n>r||!l?(s.value="",e.classList.remove("--has-file"),s.setAttribute("aria-invalid","true"),e.classList.add("--has-error")):o?(this.hasFile=!0,e.classList.add("--has-file")):(this.hasFile=!1,e.classList.remove("--has-file")),l?n<i?t=this.validationMessages.file.min_size.replace("[[var]]",i+" MB"):n>r&&(t=this.validationMessages.file.max_size.replace("[[var]]",r+" MB")):t=this.validationMessages.file.empty,t&&(a.innerText=t,this.displayFieldError(s,e,a))}displayFieldError(e,t,s){e.setAttribute("aria-invalid","true"),t.classList.add(this.classes.fieldHasError),this.classes.controlHasError&&e.classList.add(this.classes.controlHasError),s&&s.classList.remove(this.classes.hiddenErrorMessage)}clearControlError(e){e.setAttribute("aria-invalid","false"),this.classes.controlHasError&&e.classList.remove(this.classes.controlHasError);const s=t({element:e,className:"form__field"}),i=s.querySelector(".form__error");s.classList.remove(this.classes.fieldHasError),i&&(i.innerText="",i.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:s,submitDataFormat:r,requestHeaders:a,fieldGroups:o,serializerIgnoreList:l,customValidations:n,customValidationMessages:u,onStepChange:d,onSubmitStart:c,onSubmitEnd:h,onSuccess:m,onError:f,resetOnSuccess:p,scrollOnError:F,debug:g}){this.form=e,this.submitType=s||"fetch",this.submitDataFormat=r||"fromData",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",...t},this.isValid=!0,this.validator=new i({customValidations:n||{},classes:this.classes,customValidationMessages:u||null}),this.onStepChange=d||!1,this.onSubmitStart=c||!1,this.onSubmitEnd=h||!1,this.onSuccess=m||!1,this.onError=f||!1,this.fieldGroups=o||!1,this.hasFile=!1,this.serializerIgnoreList=l||[],this.resetOnSuccess=p||!0,this.scrollOnError=F||!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.debug=g||!1,this.declareHandlers(),this.debug&&this.showLog("initialized!")}submit(){if(this.debug&&this.showLog(`submitting using ${this.submitType}!`),this.submittingForm(!0),this.isValid=!0,this.form.querySelectorAll(`.${this.classes.requiredField}, .${this.classes.requiredIfFilledField}`).forEach((e=>{this.validator.validateField(e)||(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:{"Content-type":"json"===this.submitDataFormat?"application/json":"multipart/form-data",...this.requestHeaders},body:"json"===this.submitDataFormat?JSON.stringify(this.serializeData()):this.serializeData()}).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),this.scrollOnError){const e=this.form.querySelector(".form__field.--has-error");(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),s={};for(const e of t)if(!this.serializerIgnoreList.includes(e[0])){if(e[1]instanceof File&&!e[1].size&&!e[1].name)continue;s[e[0]]=e[1]}if(this.fieldGroups)for(const e in this.fieldGroups)if(Object.hasOwnProperty.call(this.fieldGroups,e)){let i=[{}];for(const r of this.fieldGroups[e])i[0][r]=t.get(r),delete s[r];s[e]=i}return e?t:s}reset(){this.form.reset(),this.form.querySelectorAll(".form__field").forEach((e=>e.classList.remove("--filled","--has-error"))),this.form.querySelectorAll(".form__control").forEach((e=>e.setAttribute("aria-invalid","false"))),this.currentStep&&this.changeStep(1)}changeStep(t){if(!this.stepChanging){const s=this.currentStepOptional?this.currentStep+"b":this.currentStep,i=this.form.querySelector('[data-step="'+s+'"]'),r=i.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.isValid&&(this.isValid=this.validator.validateField(e))})),i&&o&&this.isValid?e({element:i,enter:!1,time:200,displayType:"flex",callback:()=>{i.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(s,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 s=t.join(""),i=new RegExp("[^"+s+"0-9]","g");return e.toString().replace(i,"")}filterFormattedQuantity(e,t=".",s=",",i){const r=s?e.toString().split(s):[e],a=r[0].replace(/\B(?=(\d{3})+(?!\d))/g,t);let o="";return o=i>0&&r[1]&&r[1].length?a+s+r[1].slice(0,i):a,o}filterMoneyAmount(e,t="$",s=".",i=",",r){if(!e||e==t)return"";let a=this.filterNumber(e,[i||""]);return a=this.filterFormattedQuantity(a,s,i,r),`${t} ${a}`}filterPhoneNumber(e){return e.replace(/[a-zA-Z*'";:\\/?!@#$%^&=_`~]/g,"")}togglePasswordVisibility(e){const t=e.parentElement.querySelector(".form__control");if(t){const s="password"===t.getAttribute("type")?"text":"password";t.setAttribute("type",s),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(),e.submit()})),this.validator.realTimeValidations(this.form),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(".form__field.--number input").forEach((e=>{const s=this,i=t({element:e,className:"form__field"}),r=i&&i.dataset.thousandsSeparator?i.dataset.thousandsSeparator:null,a=i&&i.dataset.decimalSeparator?i.dataset.decimalSeparator:"",o=i&&i.dataset.decimals?i.dataset.decimals:"";function l(){e.value=s.filterNumber(e.value,[a])}e.addEventListener("focus",l),e.addEventListener("input",l),e.addEventListener("paste",l),e.addEventListener("blur",(()=>{e.value=r?s.filterFormattedQuantity(e.value,r,a,parseInt(o)):s.filterNumber(e.value)}))})),this.form.querySelectorAll(".form__field.--money-amount input").forEach((e=>{const s=this,i=t({element:e,className:"form__field"}),r=i&&i.dataset.currency?i.dataset.currency:"$",a=i&&i.dataset.thousandsSeparator?i.dataset.thousandsSeparator:".",o=i&&i.dataset.decimalSeparator?i.dataset.decimalSeparator:"",l=i&&i.dataset.decimals?i.dataset.decimals:"";function n(){e.value=s.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={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 i{constructor({customValidations:e,classes:i,customValidationMessages:s}){this.customValidations=e,this.validationMessages=s||t,this.classes=i}validateField(e){const t=e.dataset.type;e.classList.contains(this.classes.requiredField);const i=e.classList.contains(this.classes.requiredIfFilledField),s=e.querySelector(".form__error"),r=["radio","checkbox"].includes(t)?e.querySelector(".form__control:checked"):e.querySelector(".form__control"),a=r?r.getAttribute("name"):"",o=Object.keys(this.customValidations);if(r||this.throwError("control not found."),a||this.throwError("control name not found."),r.value){if(r.value){switch(t){case"email":if(!this.isValidEmail(r.value))return s&&(s.innerText=this.validationMessages.email.invalid),this.displayFieldError(r,e,s),!1;break;case"password_repeat":{const t=document.getElementById("password");if(t&&r.value!=t.value)return s&&(s.innerText=this.validationMessages.password_repeat.unequal),this.displayFieldError(r,e,s),!1;break}case"cuil":case"cuit":if(!this.isValidCuitCuil(r.value))return s&&(s.innerText=this.validationMessages.cuil.invalid),this.displayFieldError(r,e,s),!1;break;case"url":if(!this.isValidUrl(r.value))return s&&(s.innerText=this.validationMessages.url.invalid),this.displayFieldError(r,e,s),!1;break;case"money":const t=r.dataset.currency?r.dataset.currency:"$";if(""==r.value||r.value==t)return s&&(s.innerText=this.validationMessages.default.empty),this.displayFieldError(r,e,s),!1;break;case"single-checkbox":if(!r.checked)return this.displayFieldError(r,e,s),s&&(s.innerText=this.validationMessages[a]?this.validationMessages[a].empty:this.validationMessages.default.empty),!1}for(const i of o)if(t===i)for(const i of this.customValidations[t])if(!i.condition(r.value))return s&&(s.innerText=i.message||""),this.displayFieldError(r,e,s),!1}}else if(!i)return this.displayFieldError(r,e,s),s&&(s.innerText=this.validationMessages[a]?this.validationMessages[a].empty:this.validationMessages.default.empty),!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("--has-error")):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 t=(({element:e,className:t})=>{if(!e)return!1;for(;e&&!e.classList.contains(t);)e=!!e.parentElement&&e.parentElement;return e})({element:e,className:"form__field"}),i=t.querySelector(".form__error");t.classList.remove(this.classes.fieldHasError),i&&(i.innerText="",i.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:s,submitDataFormat:r,requestHeaders:a,fieldGroups:o,serializerIgnoreList:l,customValidations:n,customValidationMessages:u,onSubmitStart:d,onSubmitEnd:c,onSuccess:h,onError:m,resetOnSuccess:f,debug:p}){this.form=e,this.submitType=s||"fetch",this.submitDataFormat=r||"fromData",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",...t},this.isValid=!0,this.validator=new i({customValidations:n||{},classes:this.classes,customValidationMessages:u||null}),this.onSubmitStart=d||!1,this.onSubmitEnd=c||!1,this.onSuccess=h||!1,this.onError=m||!1,this.fieldGroups=o||!1,this.hasFile=!1,this.serializerIgnoreList=l||[],this.resetOnSuccess=f||!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.debug=p||!1,this.declareHandlers(),this.debug&&this.showLog("initialized!")}submit(){if(this.debug&&this.showLog(`submitting using ${this.submitType}!`),this.submittingForm(!0),this.isValid=!0,this.form.querySelectorAll(`.${this.classes.requiredField}, .${this.classes.requiredIfFilledField}`).forEach((e=>{this.validator.validateField(e)||(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:{"Content-type":"json"===this.submitDataFormat?"application/json":"multipart/form-data",...this.requestHeaders},body:"json"===this.submitDataFormat?JSON.stringify(this.serializeData()):this.serializeData()}).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{this.submittingForm(!1);const e=this.form.querySelector(".form__field.--has-error");(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","--has-error"))),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.isValid&&(this.isValid=this.validator.validateField(e))})),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)}})}}):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){return e.replace(/[^0-9]/g,"")}filterMoneyAmount(e,t="$"){if(!e||e==t)return"";return`${t} ${this.filterNumber(e).toString().replace(/\B(?=(\d{3})+(?!\d))/g,".")}`}filterPhoneNumber(e){return e.replace(/[a-zA-Z*'";:\\/?!@#$%^&=_`~]/g,"")}togglePasswordVisibility(e){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(),e.submit()})),this.validator.realTimeValidations(this.form),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(".form__field.--number input").forEach((e=>{e.addEventListener("input",(()=>{e.value=this.filterNumber(e.value)})),e.addEventListener("paste",(()=>{e.value=this.filterNumber(e.value)}))})),this.form.querySelectorAll(".form__field.--money-amount input").forEach((e=>{const t=e.dataset.currency?e.dataset.currency:"$";e.addEventListener("input",(()=>{e.value=this.filterMoneyAmount(e.value,t)})),e.addEventListener("paste",(()=>{e.value=this.filterMoneyAmount(e.value,t)}))})),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:s,displayType:i,callback:r})=>{e.style.opacity=t?0:1,t&&(e.style.display=i||"block");let a=+new Date;!function i(){e.style.opacity=t?+e.style.opacity+(new Date-a)/(s||200):+e.style.opacity-(new Date-a)/(s||200),a=+new Date,t&&+e.style.opacity<1||!t&&+e.style.opacity>0?window.requestAnimationFrame&&requestAnimationFrame(i)||setTimeout(i,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},s={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 i{constructor({customValidations:e,classes:t,customValidationMessages:i}){this.customValidations=e,this.validationMessages=i||s,this.classes=t}validateField(e){const t=e.dataset.type,s=["radio","checkbox"].includes(t),i=e.classList.contains(this.classes.requiredIfFilledField),r=e.querySelector(".form__error"),a=e.querySelector(".form__control"),o=s?e.querySelector(".form__control:checked"):null,l=a?a.getAttribute("name"):"",n=Object.keys(this.customValidations);if("name"==l&&console.log(s,o,a.value),a||this.throwError("control not found."),l||this.throwError("control name not found."),s&&!o||!a.value){if(!i)return this.displayFieldError(a,e,r),r&&(r.innerText=this.validationMessages[l]?this.validationMessages[l].empty:this.validationMessages.default.empty),!1}else if(a.value){switch(t){case"email":if(!this.isValidEmail(a.value))return r&&(r.innerText=this.validationMessages.email.invalid),this.displayFieldError(a,e,r),!1;break;case"password_repeat":{const t=document.getElementById("password");if(t&&a.value!=t.value)return r&&(r.innerText=this.validationMessages.password_repeat.unequal),this.displayFieldError(a,e,r),!1;break}case"cuil":case"cuit":if(!this.isValidCuitCuil(a.value))return r&&(r.innerText=this.validationMessages.cuil.invalid),this.displayFieldError(a,e,r),!1;break;case"url":if(!this.isValidUrl(a.value))return r&&(r.innerText=this.validationMessages.url.invalid),this.displayFieldError(a,e,r),!1;break;case"money":const t=a.dataset.currency?a.dataset.currency:"$";if(""==a.value||a.value==t)return r&&(r.innerText=this.validationMessages.default.empty),this.displayFieldError(a,e,r),!1;break;case"single-checkbox":if(!a.checked)return this.displayFieldError(a,e,r),r&&(r.innerText=this.validationMessages[l]?this.validationMessages[l].empty:this.validationMessages.default.empty),!1}for(const s of n)if(t===s)for(const s of this.customValidations[t])if(!s.condition(a.value))return r&&(r.innerText=s.message||""),this.displayFieldError(a,e,r),!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 s=e.toString().split("");if(11!=s.length)return!1;s=s.map((e=>parseInt(e)));const i=parseInt(s.pop());let r=11-s.reduce(((e,s,i)=>e+s*t[i]),0)%11;return 10==r&&(r=9),11==r&&(r=0),r==i}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 s=e.querySelector(".form__control"),i=parseFloat(e.dataset.minSize),r=parseFloat(e.dataset.maxSize),a=e.querySelector(".form__error"),o=s.files[0].name,l=s.files[0].size,n=parseFloat(s.files.length?(l/1048576).toFixed(1):0);n>r||!l?(s.value="",e.classList.remove("--has-file"),s.setAttribute("aria-invalid","true"),e.classList.add("--has-error")):o?(this.hasFile=!0,e.classList.add("--has-file")):(this.hasFile=!1,e.classList.remove("--has-file")),l?n<i?t=this.validationMessages.file.min_size.replace("[[var]]",i+" MB"):n>r&&(t=this.validationMessages.file.max_size.replace("[[var]]",r+" MB")):t=this.validationMessages.file.empty,t&&(a.innerText=t,this.displayFieldError(s,e,a))}displayFieldError(e,t,s){e.setAttribute("aria-invalid","true"),t.classList.add(this.classes.fieldHasError),this.classes.controlHasError&&e.classList.add(this.classes.controlHasError),s&&s.classList.remove(this.classes.hiddenErrorMessage)}clearControlError(e){e.setAttribute("aria-invalid","false"),this.classes.controlHasError&&e.classList.remove(this.classes.controlHasError);const s=t({element:e,className:"form__field"}),i=s.querySelector(".form__error");s.classList.remove(this.classes.fieldHasError),i&&(i.innerText="",i.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:s,submitDataFormat:r,requestHeaders:a,fieldGroups:o,serializerIgnoreList:l,customValidations:n,customValidationMessages:u,onStepChange:d,onSubmitStart:c,onSubmitEnd:h,onSuccess:m,onError:f,resetOnSuccess:p,scrollOnError:F,debug:g}){this.form=e,this.submitType=s||"fetch",this.submitDataFormat=r||"fromData",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",...t},this.isValid=!0,this.validator=new i({customValidations:n||{},classes:this.classes,customValidationMessages:u||null}),this.onStepChange=d||!1,this.onSubmitStart=c||!1,this.onSubmitEnd=h||!1,this.onSuccess=m||!1,this.onError=f||!1,this.fieldGroups=o||!1,this.hasFile=!1,this.serializerIgnoreList=l||[],this.resetOnSuccess=p||!0,this.scrollOnError=F||!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.debug=g||!1,this.declareHandlers(),this.debug&&this.showLog("initialized!")}submit(){if(this.debug&&this.showLog(`submitting using ${this.submitType}!`),this.submittingForm(!0),this.isValid=!0,this.form.querySelectorAll(`.${this.classes.requiredField}, .${this.classes.requiredIfFilledField}`).forEach((e=>{this.validator.validateField(e)||(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:{"Content-type":"json"===this.submitDataFormat?"application/json":"multipart/form-data",...this.requestHeaders},body:"json"===this.submitDataFormat?JSON.stringify(this.serializeData()):this.serializeData()}).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),this.scrollOnError){const e=this.form.querySelector(".form__field.--has-error");(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),s={};for(const e of t)if(!this.serializerIgnoreList.includes(e[0])){if(e[1]instanceof File&&!e[1].size&&!e[1].name)continue;s[e[0]]=e[1]}if(this.fieldGroups)for(const e in this.fieldGroups)if(Object.hasOwnProperty.call(this.fieldGroups,e)){let i=[{}];for(const r of this.fieldGroups[e])i[0][r]=t.get(r),delete s[r];s[e]=i}return e?t:s}reset(){this.form.reset(),this.form.querySelectorAll(".form__field").forEach((e=>e.classList.remove("--filled","--has-error"))),this.form.querySelectorAll(".form__control").forEach((e=>e.setAttribute("aria-invalid","false"))),this.currentStep&&this.changeStep(1)}changeStep(t){if(!this.stepChanging){const s=this.currentStepOptional?this.currentStep+"b":this.currentStep,i=this.form.querySelector('[data-step="'+s+'"]'),r=i.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.isValid&&(this.isValid=this.validator.validateField(e))})),i&&o&&this.isValid?e({element:i,enter:!1,time:200,displayType:"flex",callback:()=>{i.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(s,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 s=t.join(""),i=new RegExp("[^"+s+"0-9]","g");return e.toString().replace(i,"")}filterFormattedQuantity(e,t=".",s=",",i){const r=s?e.toString().split(s):[e],a=r[0].replace(/\B(?=(\d{3})+(?!\d))/g,t);let o="";return o=i>0&&r[1]&&r[1].length?a+s+r[1].slice(0,i):a,o}filterMoneyAmount(e,t="$",s=".",i=",",r){if(!e||e==t)return"";let a=this.filterNumber(e,[i||""]);return a=this.filterFormattedQuantity(a,s,i,r),`${t} ${a}`}filterPhoneNumber(e){return e.replace(/[a-zA-Z*'";:\\/?!@#$%^&=_`~]/g,"")}togglePasswordVisibility(e){const t=e.parentElement.querySelector(".form__control");if(t){const s="password"===t.getAttribute("type")?"text":"password";t.setAttribute("type",s),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(),e.submit()})),this.validator.realTimeValidations(this.form),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(".form__field.--number input").forEach((e=>{const s=this,i=t({element:e,className:"form__field"}),r=i&&i.dataset.thousandsSeparator?i.dataset.thousandsSeparator:null,a=i&&i.dataset.decimalSeparator?i.dataset.decimalSeparator:"",o=i&&i.dataset.decimals?i.dataset.decimals:"";function l(){e.value=s.filterNumber(e.value,[a])}e.addEventListener("focus",l),e.addEventListener("input",l),e.addEventListener("paste",l),e.addEventListener("blur",(()=>{e.value=r?s.filterFormattedQuantity(e.value,r,a,parseInt(o)):s.filterNumber(e.value)}))})),this.form.querySelectorAll(".form__field.--money-amount input").forEach((e=>{const s=this,i=t({element:e,className:"form__field"}),r=i&&i.dataset.currency?i.dataset.currency:"$",a=i&&i.dataset.thousandsSeparator?i.dataset.thousandsSeparator:".",o=i&&i.dataset.decimalSeparator?i.dataset.decimalSeparator:"",l=i&&i.dataset.decimals?i.dataset.decimals:"";function n(){e.value=s.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.0.
|
|
3
|
+
"version": "1.0.5",
|
|
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",
|
|
@@ -27,12 +27,12 @@
|
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@rollup/plugin-commonjs": "^24.0.1",
|
|
29
29
|
"@rollup/plugin-node-resolve": "^15.0.1",
|
|
30
|
+
"@rollup/plugin-terser": "^0.4.3",
|
|
30
31
|
"esm": "^3.2.25",
|
|
31
32
|
"jest": "^29.5.0",
|
|
32
33
|
"jest-environment-jsdom": "^29.5.0",
|
|
33
34
|
"rollup": "^2.79.1",
|
|
34
35
|
"rollup-plugin-scss": "^4.0.0",
|
|
35
|
-
"rollup-plugin-terser": "^7.0.2",
|
|
36
36
|
"sass": "^1.60.0"
|
|
37
37
|
},
|
|
38
38
|
"files": [
|