form-father 0.1.1 → 0.1.3
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/FormFather.min.js +1 -1
- package/index.d.ts +1 -1
- package/index.js +24 -15
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/types/validators.d.ts +1 -1
package/FormFather.min.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var FormFather=function(e){"use strict";function t(e,t,r,o){return new(r||(r=Promise))((function(n,s){function i(e){try{a(o.next(e))}catch(e){s(e)}}function l(e){try{a(o.throw(e))}catch(e){s(e)}}function a(e){var t;e.done?n(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(i,l)}a((o=o.apply(e,t||[])).next())}))}function r(e){const t="FORM"===e.tagName?Array.from(e.elements):Array.from(e.querySelectorAll("input, select, textarea, button")),r=new FormData;return t.forEach((e=>{if(!(e instanceof HTMLInputElement||e instanceof HTMLSelectElement||e instanceof HTMLTextAreaElement||e instanceof HTMLButtonElement))return;if(!e.name||e.hasAttribute("data-no-serialize"))return;const{name:t,type:o}=e;if("file"===o)if("true"===e.getAttribute("multiple")){const o=e.files;if(o)for(let e=0;e<o.length;e++)r.append(`${t}[${e}]`,o[e])}else{const o=e.files;o&&o[0]&&r.append(t,o[0])}else{let n;if("select-one"===o||"select-multiple"===o){const s=e;if("select-multiple"===o){Array.from(s.selectedOptions).map((e=>e.value)).forEach(((e,o)=>{r.append(`${t}[${o}]`,e)}))}else n=s.value,n&&r.append(t,n)}else if("tel"===o)n=e.value.split(/[\s()-]/).join("").replace(/^8/,"+7");else if("checkbox"===o||"radio"===o){if(!e.checked)return;n=e.value}else if("date"===o){const t=e.getAttribute("data-date-format");n=t?function(e,t){const r=new Date(e),o=e=>e.toString().padStart(2,"0"),n=o(r.getDate()),s=o(r.getMonth()+1),i=r.getFullYear().toString();return t.replace("dd",n).replace("mm",s).replace("yyyy",i)}(e.value,t):e.value}else n=e.value;n&&"select-one"!==o&&"select-multiple"!==o&&r.append(t,n)}})),r}var o;"function"==typeof SuppressedError&&SuppressedError;const n=Symbol.for("FormFather.validators"),s=null!==(o=globalThis[n])&&void 0!==o?o:globalThis[n]=new Map;function i(e,t,r,{override:o=!1}={}){!s.has(e)||o?s.set(e,{fn:t,defaultMessage:r}):console.warn(`[FormFather] Validator "${e}" already exists; pass { override: true } to replace`)}const l=e=>s.get(e);i("required",(e=>e.trim().length>0),"Пустое значение"),i("email",(e=>/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e)),"Неверный формат"),i("tel",(e=>/^\+7\d{10}$/.test(e)),"Неверный формат"),i("url",(e=>/^(https?:\/\/).+\..+/.test(e)),"Неверный формат"),i("not-numbers",(e=>!/[0-9]/.test(e)),"Неверный формат");class a{constructor(e,t){this.$submit=null,this.waitResponse=!1,this.inputs=null,this.$licensesCheckbox=null,this.$el=e,this.options=t;this.config=Object.assign({},{onSubmit:()=>{},onResponse:()=>{},onResponseSuccess:()=>{},onResponseUnsuccess:()=>{},customTypeError:null,loaderColor:"#fff",showLoaderButton:!0,scrollToFirstErroredInput:!0,logging:!1,inputSelector:".input",inputWrapperSelector:".input-primary"},a.defaultParams,t),this.$el?(this.$submit=this.$el.querySelector('input[type="submit"], button[type="submit"]'),this.isCorrectArguments()&&this.initialization()):console.warn("Empty $el")}getOptions(){return this.options}static setDefaultParams(e){this.defaultParams=Object.assign(Object.assign({},this.defaultParams),e)}initialization(){this.inputs=this.$el.querySelectorAll(this.config.inputSelector),this.$licensesCheckbox=this.$el.querySelector('input[data-input-name="user-consent"]'),this.$licensesCheckbox&&(this.$licensesCheckbox.checked?this.enableSubmit():this.disableSubmit(),this.$licensesCheckbox.addEventListener("change",(()=>{this.$licensesCheckbox.checked?this.enableSubmit():this.disableSubmit()})));const e=()=>t(this,void 0,void 0,(function*(){var e;const t=this.$el.getAttribute("action")||"",o=(null===(e=this.$el.getAttribute("method"))||void 0===e?void 0:e.toUpperCase())||"POST",n=this.$el.getAttribute("enctype")||"application/x-www-form-urlencoded";let s=null,i={};const l=r(this.$el);let a={};if(l.forEach(((e,t)=>{a[t]=e})),this.config.logging)for(const e of l.keys())console.log(l.get(e));switch("function"==typeof this.config.wrapData&&(a=this.config.wrapData(a)),n){case"application/x-www-form-urlencoded":s=new URLSearchParams(r(this.$el)).toString(),i["Content-Type"]="application/x-www-form-urlencoded";break;case"multipart/form-data":s=r(this.$el);break;case"text/plain":s=Array.from(r(this.$el)).map((([e,t])=>`${encodeURIComponent(e)}=${encodeURIComponent(t)}`)).join("\n"),i["Content-Type"]="text/plain";break;case"application/json":s=JSON.stringify(a),i["Content-Type"]="application/json";break;default:console.warn(`Неизвестный enctype: ${n}. Используется application/x-www-form-urlencoded.`),s=new URLSearchParams(r(this.$el)).toString(),i["Content-Type"]="application/x-www-form-urlencoded"}return fetch(t,{method:o,body:s,headers:i})})),o=()=>t(this,void 0,void 0,(function*(){var t,r,o,n,s,i,l,a;if(!this.waitResponse){!0===this.config.showLoaderButton&&this.showLoader(),null===(r=(t=this.config).onSubmit)||void 0===r||r.call(t,this),this.waitResponse=!0;const c=yield e(),u=yield c.json();if(this.waitResponse=!1,!0===this.config.showLoaderButton&&this.hideLoader(),null===(n=(o=this.config).onResponse)||void 0===n||n.call(o,u,this),200===c.status)if(function(e){if(Object.prototype.hasOwnProperty.call(e,"redirect-url")&&(window.location.href=e["redirect-url"]),Object.prototype.hasOwnProperty.call(e,"reload")&&!0===e.reload&&window.location.reload(),Object.prototype.hasOwnProperty.call(e,"error-toast")){const t=document.querySelector('[data-toast-name="formErrorToast"]');if(t){const r=t.querySelector(".toast__text");r&&(r.textContent=e["error-toast"],window.Toast.showToast("formErrorToast",{removeAfterClose:!1}))}}}(u),!0===u.success)null===(i=(s=this.config).onResponseSuccess)||void 0===i||i.call(s,u,this);else if(null===(a=(l=this.config).onResponseUnsuccess)||void 0===a||a.call(l,u,this),!0===u.error&&(u["error-msg"]&&this.showErrorForm(u["error-msg"]),u.errors)){const e=[];u.errors.forEach((t=>{const r=this.$el.querySelector(`input[name="${t.name}"]`);r?(e.push(r),this.showError(r,t["error-msg"])):console.warn(`Не найдено поле с именем: ${t.name}, для вывода ошибки: ${t["error-msg"]}`)})),!0===this.config.scrollToFirstErroredInput&&this.scrollToFirstErroredInput(e)}}}));this.$el.addEventListener("submit",(e=>t(this,void 0,void 0,(function*(){e.preventDefault();(yield this.validate())&&(!this.$licensesCheckbox||this.$licensesCheckbox&&this.$licensesCheckbox.checked)&&o()}))))}showError(e,t){(function(e,t){if(null==e)return null;let r=e;for(;r;){if(r.matches(t))return r;r=r.parentElement}return null})(e,this.config.inputWrapperSelector).showError(t)}showLoader(){var e;const t=`\n\t\t\t<svg height="38" viewBox="0 0 38 38" width="38" xmlns="http://www.w3.org/2000/svg">\n\t\t\t\t<defs>\n\t\t\t\t<linearGradient id="form-father-loader" x1="8.042%" x2="65.682%" y1="0%" y2="23.865%">\n\t\t\t\t\t<stop offset="0%" stop-color="${this.config.loaderColor}" stop-opacity="0"/>\n\t\t\t\t\t<stop offset="63.146%" stop-color="${this.config.loaderColor}" stop-opacity=".631"/>\n\t\t\t\t\t<stop offset="100%" stop-color="${this.config.loaderColor}"/>\n\t\t\t\t</linearGradient>\n\t\t\t\t</defs>\n\t\t\t\t<g fill-rule="evenodd" fill="none">\n\t\t\t\t<g transform="translate(1 1)">\n\t\t\t\t\t<path d="M36 18c0-9.94-8.06-18-18-18" id="Oval-2" stroke-width="5" stroke="url(#form-father-loader)"></path>\n\t\t\t\t\t<circle cx="36" cy="18" fill="${this.config.loaderColor}" r="1"></circle>\n\t\t\t\t</g>\n\t\t\t\t</g>\n\t\t\t</svg>\n\t\t`,r=document.createElement("span");r.innerHTML=t,r.className="button__loader",null===(e=this.$submit)||void 0===e||e.insertAdjacentElement("afterbegin",r),requestAnimationFrame((()=>{r.setAttribute("data-showed","")}))}hideLoader(){var e,t;null===(e=this.$submit)||void 0===e||e.classList.remove("button--loading");const r=null===(t=this.$submit)||void 0===t?void 0:t.querySelector(".button__loader");r&&(r.classList.remove("active"),r.removeAttribute("data-showed"),setTimeout((()=>{r.remove()}),250))}hideError(e){const t=e.parentElement;t&&t.classList.contains("input__wrapper")&&(t.getAttribute("data-type-error"),t.classList.remove("input__wrapper--error"))}scrollToFirstErroredInput(e){if(e.length>0){const t=Array.from(this.$el.querySelectorAll("input"));let r=null,o=1/0;if(e.forEach((e=>{const n=t.findIndex((t=>t===e));n<o&&(o=n,r=e)})),r){const e=r.getBoundingClientRect(),t=window.pageYOffset||document.documentElement.scrollTop,o=e.top+t-window.innerHeight/2;document.documentElement.setAttribute("data-now-scrolling",""),window.scrollTo({top:o,behavior:"smooth"}),setTimeout((()=>{document.documentElement.removeAttribute("data-now-scrolling")}),800)}}}validate(){return t(this,void 0,void 0,(function*(){const e=Object.assign(Object.assign({},a.defaultValidationSchema||{}),this.config.validationSchema||{}),r=e=>console.warn(`[FormFather] Unknown validation rule "${e}"`),o=[],n=new WeakSet;let s=!0;const i=(e,t=[])=>{var o;const n=[];e.hasAttribute("required")&&n.push("required"),n.push(...t);const s=(null!==(o=e.getAttribute("data-custom-validate"))&&void 0!==o?o:"").split(",").map((e=>e.trim())).filter(Boolean);n.push(...s);const i=[];for(const e of n){const t="string"==typeof e?e:e.rule;l(t)?i.push(e):r(t)}return i},c=(e,r,...n)=>t(this,[e,r,...n],void 0,(function*(e,t,r={}){var n;if(!("checkbox"===e.type||"radio"===e.type?!e.checked:0===e.value.trim().length)||t.includes("required")){for(const i of t){const{rule:t,params:a}="string"==typeof i?{rule:i,params:void 0}:i,c=l(t);if(!(yield c.fn(e.value,e,this.$el,a))){s=!1;const i=null!==(n=r[t])&&void 0!==n?n:c.defaultMessage;return this.showError(e,i),void o.push(e)}}this.hideError(e)}else this.hideError(e)}));for(const[t,r]of Object.entries(e)){const{selector:e,rules:o=[],messages:s={}}=r,l=e?this.$el.querySelectorAll(e):this.$el.querySelectorAll(`[data-validate="${t}"]`);for(const e of Array.from(l))n.has(e)||(n.add(e),yield c(e,i(e,o),s))}const u=Array.from(this.$el.querySelectorAll("[data-custom-validate]")).filter((e=>!n.has(e)));for(const e of u)n.add(e),yield c(e,i(e,[]));return!s&&this.config.scrollToFirstErroredInput&&this.scrollToFirstErroredInput(o),s}))}disableSubmit(){var e;null===(e=this.$submit)||void 0===e||e.setAttribute("disabled","")}enableSubmit(){var e;null===(e=this.$submit)||void 0===e||e.removeAttribute("disabled")}clearInputs(){var e;null===(e=this.inputs)||void 0===e||e.forEach((e=>{var t;const r=e;"radio"===r.type||"checkbox"===r.type?r.checked=!1:(r.value="",null===(t=r.parentElement)||void 0===t||t.classList.remove("filled"),r.dispatchEvent(new Event("input")))}))}showErrorForm(e){var t;const r=this.$el.querySelectorAll(".input__wrapper"),o=r[r.length-1];let n=this.$el.querySelector(".error-block-under-input__wrapper");n&&o.nextElementSibling===n?(n.classList.add("error-block-under-input--warning"),n.querySelector(".error-block-under-input__icon").innerHTML="\x3c!-- SVG content --\x3e",n.querySelector(".error-block-under-input__main-text").textContent=e):(n=document.createElement("div"),n.className="error-block-under-input__wrapper",n.innerHTML=`\n <div class="error-block-under-input error-block-under-input--warning">\n <div class="error-block-under-input__icon-wrapper">\n <span class="error-block-under-input__icon">\n \x3c!-- SVG content --\x3e\n </span>\n <span class="error-block-under-input__icon error-block-under-input__icon--animated" style="display:none;"></span>\n </div>\n <p class="error-block-under-input__text">\n <span class="error-block-under-input__main-text">${e}</span>\n <span class="error-block-under-input__secondary-text"></span>\n </p>\n </div>`,o.insertAdjacentElement("afterend",n)),this.$el.addEventListener("input",(()=>{this.hideErrorForm()}),{passive:!0,once:!0}),null===(t=n.querySelector(".error-block-under-input"))||void 0===t||t.classList.remove("error-block-under-input--success");const s=n.querySelector(".error-block-under-input__secondary-text");s&&(s.textContent="");const i=parseFloat(n.style.height)||0,l=parseFloat(window.getComputedStyle(n).paddingTop)||0;i!==n.querySelector(".error-block-under-input").scrollHeight+16&&(n.style.height=`${i}px`,n.style.opacity="0",n.style.paddingTop=`${l}px`)}hideErrorForm(){const e=this.$el.querySelectorAll(".input__wrapper"),t=e[e.length-1].nextElementSibling;t&&t.classList.contains("error-block-under-input__wrapper")}isCorrectArguments(){return"FORM"!==this.$el.tagName?(console.warn("$el не является тегом form"),!1):!!this.$submit||(console.warn("В форме нет кнопки с типом submit"),!1)}}return a.defaultParams={},a.defaultValidationSchema={tel:{selector:'input[type="tel"]',rules:["tel"]},email:{selector:'input[type="email"]',rules:["email"]},required:{selector:"[required]",rules:["required"]},url:{selector:'input[type="url"]',rules:["url"]},"not-numbers":{selector:'input[data-validate="not-numbers"]',rules:["not-numbers"]}},e.default=a,e.getAllValidators=function(){return new Map(s)},e.getValidator=l,e.registerValidator=i,Object.defineProperty(e,"__esModule",{value:!0}),e}({});
|
|
1
|
+
var FormFather=function(t){"use strict";function e(t,e,r,o){return new(r||(r=Promise))((function(n,i){function s(t){try{a(o.next(t))}catch(t){i(t)}}function l(t){try{a(o.throw(t))}catch(t){i(t)}}function a(t){var e;t.done?n(t.value):(e=t.value,e instanceof r?e:new r((function(t){t(e)}))).then(s,l)}a((o=o.apply(t,e||[])).next())}))}function r(t){const e="FORM"===t.tagName?Array.from(t.elements):Array.from(t.querySelectorAll("input, select, textarea, button")),r=new FormData;return e.forEach((t=>{if(!(t instanceof HTMLInputElement||t instanceof HTMLSelectElement||t instanceof HTMLTextAreaElement||t instanceof HTMLButtonElement))return;if(!t.name||t.hasAttribute("data-no-serialize"))return;const{name:e,type:o}=t;if("file"===o)if("true"===t.getAttribute("multiple")){const o=t.files;if(o)for(let t=0;t<o.length;t++)r.append(`${e}[${t}]`,o[t])}else{const o=t.files;o&&o[0]&&r.append(e,o[0])}else{let n;if("select-one"===o||"select-multiple"===o){const i=t;if("select-multiple"===o){Array.from(i.selectedOptions).map((t=>t.value)).forEach(((t,o)=>{r.append(`${e}[${o}]`,t)}))}else n=i.value,n&&r.append(e,n)}else if("tel"===o)n=t.value.split(/[\s()-]/).join("").replace(/^8/,"+7");else if("checkbox"===o||"radio"===o){if(!t.checked)return;n=t.value}else if("date"===o){const e=t.getAttribute("data-date-format");n=e?function(t,e){const r=new Date(t),o=t=>t.toString().padStart(2,"0"),n=o(r.getDate()),i=o(r.getMonth()+1),s=r.getFullYear().toString();return e.replace("dd",n).replace("mm",i).replace("yyyy",s)}(t.value,e):t.value}else n=t.value;n&&"select-one"!==o&&"select-multiple"!==o&&r.append(e,n)}})),r}var o;"function"==typeof SuppressedError&&SuppressedError;const n=Symbol.for("FormFather.validators"),i=null!==(o=globalThis[n])&&void 0!==o?o:globalThis[n]=new Map;function s(t,e,r,{override:o=!1}={}){!i.has(t)||o?i.set(t,{fn:e,defaultMessage:r}):console.warn(`[FormFather] Validator "${t}" already exists; pass { override: true } to replace`)}const l=t=>i.get(t);s("required",((t,e,r)=>{if(e&&e.type){if("checkbox"===e.type)return e.checked;if("radio"===e.type){const t=r.querySelectorAll(`input[type="radio"][name="${e.name}"]`);return Array.from(t).some((t=>t.checked))}}return t.trim().length>0}),"Пустое значение"),s("email",(t=>/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(t)),"Неверный формат"),s("tel",(t=>/^\+7\d{10}$/.test(t)),"Неверный формат"),s("url",(t=>/^(https?:\/\/).+\..+/.test(t)),"Неверный формат"),s("not-numbers",(t=>!/[0-9]/.test(t)),"Неверный формат");class a{constructor(t,e){this.$submit=null,this.waitResponse=!1,this.inputs=null,this.$licensesCheckbox=null,this.$el=t,this.options=e;this.config=Object.assign({},{onSubmit:()=>{},onResponse:()=>{},onResponseSuccess:()=>{},onResponseUnsuccess:()=>{},customTypeError:null,loaderColor:"#fff",showLoaderButton:!0,scrollToFirstErroredInput:!0,logging:!1,inputSelector:".input",inputWrapperSelector:".input-primary"},a.defaultParams,e),this.$el?(this.$submit=this.$el.querySelector('input[type="submit"], button[type="submit"]'),this.isCorrectArguments()&&this.initialization()):console.warn("Empty $el")}getOptions(){return this.options}static setDefaultParams(t){this.defaultParams=Object.assign(Object.assign({},this.defaultParams),t)}initialization(){this.inputs=this.$el.querySelectorAll(this.config.inputSelector);const t=()=>e(this,void 0,void 0,(function*(){var t;const e=this.$el.getAttribute("action")||"",o=(null===(t=this.$el.getAttribute("method"))||void 0===t?void 0:t.toUpperCase())||"POST",n=this.$el.getAttribute("enctype")||"application/x-www-form-urlencoded";let i=null,s={};const l=r(this.$el);let a={};if(l.forEach(((t,e)=>{a[e]=t})),this.config.logging)for(const t of l.keys())console.log(l.get(t));switch("function"==typeof this.config.wrapData&&(a=this.config.wrapData(a)),n){case"application/x-www-form-urlencoded":i=new URLSearchParams(r(this.$el)).toString(),s["Content-Type"]="application/x-www-form-urlencoded";break;case"multipart/form-data":i=r(this.$el);break;case"text/plain":i=Array.from(r(this.$el)).map((([t,e])=>`${encodeURIComponent(t)}=${encodeURIComponent(e)}`)).join("\n"),s["Content-Type"]="text/plain";break;case"application/json":i=JSON.stringify(a),s["Content-Type"]="application/json";break;default:console.warn(`Неизвестный enctype: ${n}. Используется application/x-www-form-urlencoded.`),i=new URLSearchParams(r(this.$el)).toString(),s["Content-Type"]="application/x-www-form-urlencoded"}return fetch(e,{method:o,body:i,headers:s})})),o=()=>e(this,void 0,void 0,(function*(){var e,r,o,n,i,s,l,a;if(!this.waitResponse){!0===this.config.showLoaderButton&&this.showLoader(),null===(r=(e=this.config).onSubmit)||void 0===r||r.call(e,this),this.waitResponse=!0;const c=yield t(),u=yield c.json();if(this.waitResponse=!1,!0===this.config.showLoaderButton&&this.hideLoader(),null===(n=(o=this.config).onResponse)||void 0===n||n.call(o,u,this),200===c.status)if(function(t){if(Object.prototype.hasOwnProperty.call(t,"redirect-url")&&(window.location.href=t["redirect-url"]),Object.prototype.hasOwnProperty.call(t,"reload")&&!0===t.reload&&window.location.reload(),Object.prototype.hasOwnProperty.call(t,"error-toast")){const e=document.querySelector('[data-toast-name="formErrorToast"]');if(e){const r=e.querySelector(".toast__text");r&&(r.textContent=t["error-toast"],window.Toast.showToast("formErrorToast",{removeAfterClose:!1}))}}}(u),!0===u.success)null===(s=(i=this.config).onResponseSuccess)||void 0===s||s.call(i,u,this);else if(null===(a=(l=this.config).onResponseUnsuccess)||void 0===a||a.call(l,u,this),!0===u.error&&(u["error-msg"]&&this.showErrorForm(u["error-msg"]),u.errors)){const t=[];u.errors.forEach((e=>{const r=this.$el.querySelector(`input[name="${e.name}"]`);r?(t.push(r),this.showError(r,e["error-msg"])):console.warn(`Не найдено поле с именем: ${e.name}, для вывода ошибки: ${e["error-msg"]}`)})),!0===this.config.scrollToFirstErroredInput&&this.scrollToFirstErroredInput(t)}}}));this.$el.addEventListener("submit",(t=>e(this,void 0,void 0,(function*(){t.preventDefault();(yield this.validate())&&o()}))))}showError(t,e){(function(t,e){if(null==t)return null;let r=t;for(;r;){if(r.matches(e))return r;r=r.parentElement}return null})(t,this.config.inputWrapperSelector).showError(e)}showLoader(){var t;const e=`\n\t\t\t<svg height="38" viewBox="0 0 38 38" width="38" xmlns="http://www.w3.org/2000/svg">\n\t\t\t\t<defs>\n\t\t\t\t<linearGradient id="form-father-loader" x1="8.042%" x2="65.682%" y1="0%" y2="23.865%">\n\t\t\t\t\t<stop offset="0%" stop-color="${this.config.loaderColor}" stop-opacity="0"/>\n\t\t\t\t\t<stop offset="63.146%" stop-color="${this.config.loaderColor}" stop-opacity=".631"/>\n\t\t\t\t\t<stop offset="100%" stop-color="${this.config.loaderColor}"/>\n\t\t\t\t</linearGradient>\n\t\t\t\t</defs>\n\t\t\t\t<g fill-rule="evenodd" fill="none">\n\t\t\t\t<g transform="translate(1 1)">\n\t\t\t\t\t<path d="M36 18c0-9.94-8.06-18-18-18" id="Oval-2" stroke-width="5" stroke="url(#form-father-loader)"></path>\n\t\t\t\t\t<circle cx="36" cy="18" fill="${this.config.loaderColor}" r="1"></circle>\n\t\t\t\t</g>\n\t\t\t\t</g>\n\t\t\t</svg>\n\t\t`,r=document.createElement("span");r.innerHTML=e,r.className="button__loader",null===(t=this.$submit)||void 0===t||t.insertAdjacentElement("afterbegin",r),requestAnimationFrame((()=>{r.setAttribute("data-showed","")}))}hideLoader(){var t,e;null===(t=this.$submit)||void 0===t||t.classList.remove("button--loading");const r=null===(e=this.$submit)||void 0===e?void 0:e.querySelector(".button__loader");r&&(r.classList.remove("active"),r.removeAttribute("data-showed"),setTimeout((()=>{r.remove()}),250))}hideError(t){const e=t.parentElement;e&&e.classList.contains("input__wrapper")&&(e.getAttribute("data-type-error"),e.classList.remove("input__wrapper--error"))}scrollToFirstErroredInput(t){if(t.length>0){const e=Array.from(this.$el.querySelectorAll("input"));let r=null,o=1/0;if(t.forEach((t=>{const n=e.findIndex((e=>e===t));n<o&&(o=n,r=t)})),r){const t=r.getBoundingClientRect(),e=window.pageYOffset||document.documentElement.scrollTop,o=t.top+e-window.innerHeight/2;document.documentElement.setAttribute("data-now-scrolling",""),window.scrollTo({top:o,behavior:"smooth"}),setTimeout((()=>{document.documentElement.removeAttribute("data-now-scrolling")}),800)}}}validate(){return e(this,void 0,void 0,(function*(){const t=Object.assign(Object.assign({},a.defaultValidationSchema||{}),this.config.validationSchema||{}),r=t=>console.warn(`[FormFather] Unknown validation rule "${t}"`),o=[],n=new WeakSet;let i=!0;const s=(t,e=[])=>{var o;const n=[];t.hasAttribute("required")&&n.push("required"),n.push(...e);const i=(null!==(o=t.getAttribute("data-custom-validate"))&&void 0!==o?o:"").split(",").map((t=>t.trim())).filter(Boolean);n.push(...i);const s=[];for(const t of n){const e="string"==typeof t?t:t.rule;l(e)?s.push(t):r(e)}return s},c=(t,r,...n)=>e(this,[t,r,...n],void 0,(function*(t,e,r={}){var n;if(!("checkbox"===t.type||"radio"===t.type?!t.checked:0===t.value.trim().length)||e.includes("required")){for(const s of e){const{rule:e,params:a}="string"==typeof s?{rule:s,params:void 0}:s,c=l(e);if(!(yield c.fn(t.value,t,this.$el,a))){i=!1;const s=null!==(n=r[e])&&void 0!==n?n:c.defaultMessage;return this.showError(t,s),void o.push(t)}}this.hideError(t)}else this.hideError(t)}));for(const[e,r]of Object.entries(t)){const{selector:t,rules:o=[],messages:i={}}=r,l=t?this.$el.querySelectorAll(t):this.$el.querySelectorAll(`[data-validate="${e}"]`);for(const t of Array.from(l))n.has(t)||(n.add(t),yield c(t,s(t,o),i))}const u=Array.from(this.$el.querySelectorAll("[data-custom-validate]")).filter((t=>!n.has(t)));for(const t of u)n.add(t),yield c(t,s(t,[]));return!i&&this.config.scrollToFirstErroredInput&&this.scrollToFirstErroredInput(o),i}))}disableSubmit(){var t;null===(t=this.$submit)||void 0===t||t.setAttribute("disabled","")}enableSubmit(){var t;null===(t=this.$submit)||void 0===t||t.removeAttribute("disabled")}clearInputs(){var t;null===(t=this.inputs)||void 0===t||t.forEach((t=>{var e;const r=t;"radio"===r.type||"checkbox"===r.type?r.checked=!1:(r.value="",null===(e=r.parentElement)||void 0===e||e.classList.remove("filled"),r.dispatchEvent(new Event("input")))}))}showErrorForm(t){var e;const r=this.$el.querySelectorAll(".input__wrapper"),o=r[r.length-1];let n=this.$el.querySelector(".error-block-under-input__wrapper");n&&o.nextElementSibling===n?(n.classList.add("error-block-under-input--warning"),n.querySelector(".error-block-under-input__icon").innerHTML="\x3c!-- SVG content --\x3e",n.querySelector(".error-block-under-input__main-text").textContent=t):(n=document.createElement("div"),n.className="error-block-under-input__wrapper",n.innerHTML=`\n <div class="error-block-under-input error-block-under-input--warning">\n <div class="error-block-under-input__icon-wrapper">\n <span class="error-block-under-input__icon">\n \x3c!-- SVG content --\x3e\n </span>\n <span class="error-block-under-input__icon error-block-under-input__icon--animated" style="display:none;"></span>\n </div>\n <p class="error-block-under-input__text">\n <span class="error-block-under-input__main-text">${t}</span>\n <span class="error-block-under-input__secondary-text"></span>\n </p>\n </div>`,o.insertAdjacentElement("afterend",n)),this.$el.addEventListener("input",(()=>{this.hideErrorForm()}),{passive:!0,once:!0}),null===(e=n.querySelector(".error-block-under-input"))||void 0===e||e.classList.remove("error-block-under-input--success");const i=n.querySelector(".error-block-under-input__secondary-text");i&&(i.textContent="");const s=parseFloat(n.style.height)||0,l=parseFloat(window.getComputedStyle(n).paddingTop)||0;s!==n.querySelector(".error-block-under-input").scrollHeight+16&&(n.style.height=`${s}px`,n.style.opacity="0",n.style.paddingTop=`${l}px`)}hideErrorForm(){const t=this.$el.querySelectorAll(".input__wrapper"),e=t[t.length-1].nextElementSibling;e&&e.classList.contains("error-block-under-input__wrapper")}isCorrectArguments(){return"FORM"!==this.$el.tagName?(console.warn("$el не является тегом form"),!1):!!this.$submit||(console.warn("В форме нет кнопки с типом submit"),!1)}}return a.defaultParams={},a.defaultValidationSchema={tel:{selector:'input[type="tel"]',rules:["tel"]},email:{selector:'input[type="email"]',rules:["email"]},required:{selector:"[required]",rules:["required"]},url:{selector:'input[type="url"]',rules:["url"]},"not-numbers":{selector:'input[data-validate="not-numbers"]',rules:["not-numbers"]}},t.default=a,t.getAllValidators=function(){return new Map(i)},t.getValidator=l,t.registerValidator=s,Object.defineProperty(t,"__esModule",{value:!0}),t}({});
|
|
2
2
|
//# sourceMappingURL=FormFather.min.js.map
|
package/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
type ValidatorFn = (value: string, $input: HTMLInputElement, $form: HTMLElement, params?: any) => boolean | Promise<boolean>;
|
|
1
|
+
type ValidatorFn = (value: string, $input: HTMLInputElement | HTMLTextAreaElement, $form: HTMLElement, params?: any) => boolean | Promise<boolean>;
|
|
2
2
|
interface Validator {
|
|
3
3
|
fn: ValidatorFn;
|
|
4
4
|
defaultMessage: string;
|
package/index.js
CHANGED
|
@@ -198,7 +198,19 @@ function getAllValidators() {
|
|
|
198
198
|
return new Map(validators); // копию, чтобы никто не мутировал оригинал
|
|
199
199
|
}
|
|
200
200
|
/* ---------- built-in rules ---------- */
|
|
201
|
-
registerValidator('required',
|
|
201
|
+
registerValidator('required', (value, $input, $form) => {
|
|
202
|
+
if ($input && $input.type) {
|
|
203
|
+
if ($input.type === 'checkbox') {
|
|
204
|
+
return $input.checked;
|
|
205
|
+
}
|
|
206
|
+
if ($input.type === 'radio') {
|
|
207
|
+
const group = $form.querySelectorAll(`input[type="radio"][name="${$input.name}"]`);
|
|
208
|
+
return Array.from(group).some(el => el.checked);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
// fallback — если нет $input (например, в unit-тестах)
|
|
212
|
+
return value.trim().length > 0;
|
|
213
|
+
}, 'Пустое значение');
|
|
202
214
|
registerValidator('email', v => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v), 'Неверный формат');
|
|
203
215
|
registerValidator('tel', v => /^\+7\d{10}$/.test(v), 'Неверный формат');
|
|
204
216
|
registerValidator('url', v => /^(https?:\/\/).+\..+/.test(v), 'Неверный формат');
|
|
@@ -262,19 +274,16 @@ class Form {
|
|
|
262
274
|
}
|
|
263
275
|
initialization() {
|
|
264
276
|
this.inputs = this.$el.querySelectorAll(this.config.inputSelector);
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
this.disableSubmit();
|
|
276
|
-
});
|
|
277
|
-
}
|
|
277
|
+
/* TODO: Добавить параметр с возможностью отключать/включать кнопку, в зависимости от валидности поля. */
|
|
278
|
+
// this.$licensesCheckbox = this.$el.querySelector('input[data-input-name="user-consent"]') as HTMLInputElement;
|
|
279
|
+
// if (this.$licensesCheckbox) {
|
|
280
|
+
// if (this.$licensesCheckbox.checked) this.enableSubmit();
|
|
281
|
+
// else this.disableSubmit();
|
|
282
|
+
// this.$licensesCheckbox.addEventListener('change', () => {
|
|
283
|
+
// if (this.$licensesCheckbox!.checked) this.enableSubmit();
|
|
284
|
+
// else this.disableSubmit();
|
|
285
|
+
// });
|
|
286
|
+
// }
|
|
278
287
|
const sendData = () => __awaiter(this, void 0, void 0, function* () {
|
|
279
288
|
var _a;
|
|
280
289
|
const action = this.$el.getAttribute('action') || '';
|
|
@@ -373,7 +382,7 @@ class Form {
|
|
|
373
382
|
this.$el.addEventListener('submit', (e) => __awaiter(this, void 0, void 0, function* () {
|
|
374
383
|
e.preventDefault();
|
|
375
384
|
const isValid = yield this.validate();
|
|
376
|
-
if (isValid
|
|
385
|
+
if (isValid)
|
|
377
386
|
submit();
|
|
378
387
|
}));
|
|
379
388
|
}
|
package/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/package.json
CHANGED
package/types/validators.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
type ValidatorFn = (value: string, $input: HTMLInputElement, $form: HTMLElement, params?: any) => boolean | Promise<boolean>;
|
|
1
|
+
type ValidatorFn = (value: string, $input: HTMLInputElement | HTMLTextAreaElement, $form: HTMLElement, params?: any) => boolean | Promise<boolean>;
|
|
2
2
|
interface Validator {
|
|
3
3
|
fn: ValidatorFn;
|
|
4
4
|
defaultMessage: string;
|