form-father 0.2.7 → 0.2.8

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 CHANGED
@@ -1,2 +1,2 @@
1
- var FormFather=function(t){"use strict";function e(t,e,i,o){return new(i||(i=Promise))((function(r,n){function s(t){try{l(o.next(t))}catch(t){n(t)}}function a(t){try{l(o.throw(t))}catch(t){n(t)}}function l(t){var e;t.done?r(t.value):(e=t.value,e instanceof i?e:new i((function(t){t(e)}))).then(s,a)}l((o=o.apply(t,e||[])).next())}))}function i(t){const e="FORM"===t.tagName?Array.from(t.elements):Array.from(t.querySelectorAll("input, select, textarea, button")),i=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++)i.append(`${e}[${t}]`,o[t])}else{const o=t.files;o&&o[0]&&i.append(e,o[0])}else{let r;if("select-one"===o||"select-multiple"===o){const n=t;if("select-multiple"===o){Array.from(n.selectedOptions).map((t=>t.value)).forEach(((t,o)=>{i.append(`${e}[${o}]`,t)}))}else r=n.value,r&&i.append(e,r)}else if("tel"===o)r=t.value.split(/[\s()-]/).join("").replace(/^8/,"+7");else if("checkbox"===o||"radio"===o){if(!t.checked)return;r=t.value}else if("date"===o){const e=t.getAttribute("data-date-format");r=e?function(t,e){const i=new Date(t),o=t=>t.toString().padStart(2,"0"),r=o(i.getDate()),n=o(i.getMonth()+1),s=i.getFullYear().toString();return e.replace("dd",r).replace("mm",n).replace("yyyy",s)}(t.value,e):t.value}else r=t.value;r&&"select-one"!==o&&"select-multiple"!==o&&i.append(e,r)}})),i}var o;"function"==typeof SuppressedError&&SuppressedError;const r=Symbol.for("FormFather.validators"),n=null!==(o=globalThis[r])&&void 0!==o?o:globalThis[r]=new Map;function s(t,e,i,{override:o=!1}={}){!n.has(t)||o?n.set(t,{fn:e,defaultMessage:i}):console.warn(`[FormFather] Validator "${t}" already exists; pass { override: true } to replace`)}const a=t=>n.get(t);var l;s("required",((t,e,i)=>{if(e&&e.type){if("checkbox"===e.type)return e.checked;if("radio"===e.type){const t=i.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)),"Неверный формат");const c=Symbol.for("formfather.shared"),d=null!==(l=globalThis[c])&&void 0!==l?l:globalThis[c]={defaultParams:{},defaultValidationSchema:void 0},u={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"]}};class p{static get defaultParams(){return d.defaultParams}static set defaultParams(t){d.defaultParams=t}static get defaultValidationSchema(){var t;return null!==(t=d.defaultValidationSchema)&&void 0!==t?t:d.defaultValidationSchema=u}static set defaultValidationSchema(t){d.defaultValidationSchema=t}constructor(t,i){var o;this.$submit=null,this.waitResponse=!1,this.inputs=null,this._anim={duration:220,easing:"ease",paddingTopOpened:16,iconDuration:700},this.$el=t,this.options=i;this.config=Object.assign({},{onSubmit:()=>{},onResponse:()=>{},onResponseSuccess:()=>{},onResponseUnsuccess:()=>{},customTypeError:null,loaderColor:"#fff",showLoaderButton:!0,scrollToFirstErroredInput:!0,logging:!1,inputSelector:".input",inputWrapperSelector:".input-primary"},p.defaultParams,i),this.$el?(this.$submit=this.$el.querySelector('input[type="submit"], button[type="submit"]'),this._onSubmitClickHandler=t=>e(this,void 0,void 0,(function*(){var e,i,o,r;t.preventDefault(),null===(i=(e=this.config).onBeforeValidate)||void 0===i||i.call(e,this);const n=yield this.validate();null===(r=(o=this.config).onAfterValidate)||void 0===r||r.call(o,n,this),n&&(yield this.submit())})),null===(o=this.$submit)||void 0===o||o.addEventListener("click",this._onSubmitClickHandler),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),this._onSubmitHandler=t=>e(this,void 0,void 0,(function*(){var e,i,o,r;t.preventDefault(),null===(i=(e=this.config).onBeforeValidate)||void 0===i||i.call(e,this);const n=yield this.validate();null===(r=(o=this.config).onAfterValidate)||void 0===r||r.call(o,n,this),n&&this.submit()})),this.$el.addEventListener("submit",this._onSubmitHandler)}showError(t,e){(function(t,e){if(null==t)return null;let i=t;for(;i;){if(i.matches(e))return i;i=i.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`,i=document.createElement("span");i.innerHTML=e,i.className="button__loader",null===(t=this.$submit)||void 0===t||t.insertAdjacentElement("afterbegin",i),requestAnimationFrame((()=>{i.setAttribute("data-showed","")}))}hideLoader(){var t,e;null===(t=this.$submit)||void 0===t||t.classList.remove("button--loading");const i=null===(e=this.$submit)||void 0===e?void 0:e.querySelector(".button__loader");i&&(i.classList.remove("active"),i.removeAttribute("data-showed"),setTimeout((()=>{i.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 i=null,o=1/0;if(t.forEach((t=>{const r=e.findIndex((e=>e===t));r<o&&(o=r,i=t)})),i){const t=i.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,arguments,void 0,(function*(t=this.$el){const i=Object.assign(Object.assign({},p.defaultValidationSchema||{}),this.config.validationSchema||{}),o=t=>console.warn(`[FormFather] Unknown validation rule "${t}"`),r=[],n=new WeakSet;let s=!0;const l=(t,e=[])=>{var i;const r=[];t.hasAttribute("required")&&r.push("required"),r.push(...e);const n=(null!==(i=t.getAttribute("data-custom-validate"))&&void 0!==i?i:"").split(",").map((t=>t.trim())).filter(Boolean);r.push(...n);const s=[];for(const t of r){const e="string"==typeof t?t:t.rule;a(e)?s.push(t):o(e)}return s},c=(i,o,...n)=>e(this,[i,o,...n],void 0,(function*(e,i,o={}){if(e.hasAttribute("data-no-validate"))return;if(!("checkbox"===e.type||"radio"===e.type?!e.checked:0===e.value.trim().length)||i.includes("required")){for(const n of i){const{rule:i,params:l}="string"==typeof n?{rule:n,params:void 0}:n,c=a(i),d=yield c.fn(e.value,e,t,l),u="object"==typeof d&&null!==d,p=u?!0===d.valid:!!d;if(u&&d.effect&&(yield d.effect({value:e.value,$input:e,$form:t,params:l})),!p){s=!1;const t=d,n=u&&"string"==typeof t.message&&t.message||o[i]||c.defaultMessage;return this.showError(e,n),void r.push(e)}if(u&&d.stopOthers)return}this.hideError(e)}else this.hideError(e)}));for(const[e,o]of Object.entries(i)){const{selector:i,rules:r=[],messages:s={}}=o,a=i?t.querySelectorAll(i):t.querySelectorAll(`[data-validate="${e}"]`);for(const t of Array.from(a))n.has(t)||(n.add(t),yield c(t,l(t,r),s))}const d=Array.from(t.querySelectorAll("[data-custom-validate]")).filter((t=>!n.has(t)));for(const t of d)n.add(t),yield c(t,l(t,[]));return!s&&this.config.scrollToFirstErroredInput&&this.scrollToFirstErroredInput(r.filter((t=>!t.hasAttribute("data-no-error-scroll")))),s}))}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 i=t;"radio"===i.type||"checkbox"===i.type?i.checked=!1:(i.value="",null===(e=i.parentElement)||void 0===e||e.classList.remove("filled"),i.dispatchEvent(new Event("input")))}))}_prefersReducedMotion(){var t;return"undefined"!=typeof window&&(null===(t=window.matchMedia)||void 0===t?void 0:t.call(window,"(prefers-reduced-motion: reduce)").matches)}_canAnimate(t){return!(!t||!("animate"in t)||this._prefersReducedMotion())}_cancelAnimations(t){var e;null===(e=null==t?void 0:t.getAnimations)||void 0===e||e.call(t).forEach((t=>t.cancel()))}showErrorForm(t){var e;const i=this.$el.querySelectorAll(this.config.inputWrapperSelector),o=i[i.length-1];let r=this.$el.querySelector(".error-block-under-input__wrapper");r&&o.nextElementSibling===r?(r.style.boxSizing="border-box",r.style.overflow="hidden"):(r=document.createElement("div"),r.className="error-block-under-input__wrapper",r.innerHTML='\n <div class="error-block-under-input error-block-under-input--warning" style="display:grid;grid-template-columns:auto 1fr;gap:8px;align-items:start;">\n <div class="error-block-under-input__icon-wrapper" style="position:relative;width:20px;height:20px;">\n <span class="error-block-under-input__icon" style="display:block;width:20px;height:20px;"></span>\n <span class="error-block-under-input__icon error-block-under-input__icon--animated" style="display:block;position:absolute;inset:0;"></span>\n </div>\n <p class="error-block-under-input__text" style="margin:0;">\n <span class="error-block-under-input__main-text"></span>\n <span class="error-block-under-input__secondary-text"></span>\n </p>\n </div>\n ',Object.assign(r.style,{boxSizing:"border-box",overflow:"hidden",height:"0px",paddingTop:"0px",opacity:"0"}),o.insertAdjacentElement("afterend",r)),r.querySelector(".error-block-under-input__main-text").textContent=t;const n=r.querySelector(".error-block-under-input__secondary-text");n&&(n.textContent=""),null===(e=r.querySelector(".error-block-under-input"))||void 0===e||e.classList.remove("error-block-under-input--success"),r.querySelector(".error-block-under-input");const s=r.style.height,a=r.style.paddingTop;r.style.height="auto",r.style.paddingTop=`${this._anim.paddingTopOpened}px`;const l=r.clientHeight;if(r.style.height=s||"0px",r.style.paddingTop=a||"0px",parseFloat(r.style.height)===l&&1===parseFloat(r.style.opacity||"1"))this._ringIcon(r);else{if(this._cancelAnimations(r),this._canAnimate(r)){r.animate([{height:`${parseFloat(r.style.height)||0}px`,paddingTop:`${parseFloat(r.style.paddingTop)||0}px`,opacity:parseFloat(r.style.opacity||"0")},{height:`${l}px`,paddingTop:`${this._anim.paddingTopOpened}px`,opacity:1}],{duration:this._anim.duration,easing:this._anim.easing,fill:"forwards"}).addEventListener("finish",(()=>{r.style.height="auto",r.style.paddingTop=`${this._anim.paddingTopOpened}px`,r.style.opacity="1"}))}else r.style.height="auto",r.style.paddingTop=`${this._anim.paddingTopOpened}px`,r.style.opacity="1";this._ringIcon(r)}this.$el.addEventListener("input",(()=>this.hideErrorForm()),{passive:!0,once:!0})}hideErrorForm(){const t=this.$el.querySelectorAll(this.config.inputWrapperSelector),e=t[t.length-1].nextElementSibling;if(!e||!e.classList.contains("error-block-under-input__wrapper"))return;if((""===e.style.height||"auto"===e.style.height)&&(e.style.height=`${e.clientHeight}px`),e.style.paddingTop=e.style.paddingTop||`${this._anim.paddingTopOpened}px`,e.style.opacity=e.style.opacity||"1",this._cancelAnimations(e),this._canAnimate(e)){e.animate([{height:`${parseFloat(e.style.height)||e.clientHeight}px`,paddingTop:`${parseFloat(e.style.paddingTop)||this._anim.paddingTopOpened}px`,opacity:parseFloat(e.style.opacity||"1")},{height:"0px",paddingTop:"0px",opacity:0}],{duration:this._anim.duration,easing:this._anim.easing,fill:"forwards"}).addEventListener("finish",(()=>{e.remove()}))}else e.remove()}_ringIcon(t){const e=t.querySelector(".error-block-under-input__icon--animated");e&&(this._cancelAnimations(e),this._canAnimate(e)&&e.animate([{transform:"rotate(0deg) scale(1)",opacity:0},{transform:"rotate(-8deg) scale(1.05)",opacity:1,offset:.15},{transform:"rotate(8deg) scale(1.05)",opacity:1,offset:.3},{transform:"rotate(-6deg) scale(1.03)",opacity:1,offset:.45},{transform:"rotate(6deg) scale(1.03)",opacity:1,offset:.6},{transform:"rotate(0deg) scale(1)",opacity:0}],{duration:this._anim.iconDuration,easing:"ease"}))}destroy(){var t,e,i;this._onSubmitHandler&&(this.$el.removeEventListener("submit",this._onSubmitHandler),this._onSubmitHandler=void 0),this._onSubmitClickHandler&&(null===(t=this.$submit)||void 0===t||t.removeEventListener("click",this._onSubmitClickHandler),this._onSubmitClickHandler=void 0);const o=this.$el.querySelector(".error-block-under-input__wrapper");o&&(this._cancelAnimations(o),o.remove()),null===(e=this.$submit)||void 0===e||e.classList.remove("button--loading");const r=null===(i=this.$submit)||void 0===i?void 0:i.querySelector(".button__loader");r&&r.remove();this.$el.querySelectorAll("input, textarea").forEach((t=>{t instanceof HTMLInputElement&&this.hideError(t)})),document.documentElement.removeAttribute("data-now-scrolling"),this.inputs=null,this.$submit=null,this.waitResponse=!1}isCorrectArguments(){return"FORM"!==this.$el.tagName?(console.warn("$el не является тегом form"),!1):!!this.$submit||(console.warn("В форме нет кнопки с типом submit"),!1)}sendData(){return 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",r=this.$el.getAttribute("enctype")||"application/x-www-form-urlencoded";let n=null,s={};const a=i(this.$el);let l={};if(a.forEach(((t,e)=>{l[e]=t})),this.config.logging)for(const t of a.keys())console.log(a.get(t));switch("function"==typeof this.config.wrapData&&(l=this.config.wrapData(l)),r){case"application/x-www-form-urlencoded":n=new URLSearchParams(i(this.$el)).toString(),s["Content-Type"]="application/x-www-form-urlencoded";break;case"multipart/form-data":n=i(this.$el);break;case"text/plain":n=Array.from(i(this.$el)).map((([t,e])=>`${encodeURIComponent(t)}=${encodeURIComponent(e)}`)).join("\n"),s["Content-Type"]="text/plain";break;case"application/json":n=JSON.stringify(l),s["Content-Type"]="application/json";break;default:console.warn(`Неизвестный enctype: ${r}. Используется application/x-www-form-urlencoded.`),n=new URLSearchParams(i(this.$el)).toString(),s["Content-Type"]="application/x-www-form-urlencoded"}return fetch(e,{method:o,body:n,headers:s})}))}submit(){return e(this,void 0,void 0,(function*(){var t,e,i,o,r,n,s,a;if(!this.waitResponse){!0===this.config.showLoaderButton&&this.showLoader(),null===(e=(t=this.config).onSubmit)||void 0===e||e.call(t,this),this.waitResponse=!0;const l=yield this.sendData(),c=yield l.json();if(this.waitResponse=!1,!0===this.config.showLoaderButton&&this.hideLoader(),null===(o=(i=this.config).onResponse)||void 0===o||o.call(i,c,this),200===l.status){if(!0===c.success)null===(n=(r=this.config).onResponseSuccess)||void 0===n||n.call(r,c,this);else if(null===(a=(s=this.config).onResponseUnsuccess)||void 0===a||a.call(s,c,this),!0===c.error&&(c["error-msg"]&&this.showErrorForm(c["error-msg"]),c.errors)){const t=[];c.errors.forEach((e=>{const i=this.$el.querySelector(`input[name="${e.name}"]`);i?(t.push(i),this.showError(i,e["error-msg"])):console.warn(`Не найдено поле с именем: ${e.name}, для вывода ошибки: ${e["error-msg"]}`)})),!0===this.config.scrollToFirstErroredInput&&this.scrollToFirstErroredInput(t)}!function(t){if(Object.prototype.hasOwnProperty.call(t,"redirect-url"))if(t["redirect-url-delay"]){const e=Number(t["redirect-url-delay"]);setTimeout((()=>{window.location.href=t["redirect-url"]}),e)}else window.location.href=t["redirect-url"];else if(Object.prototype.hasOwnProperty.call(t,"reload")){if(!0===t.reload)if(t["reload-delay"]){const e=Number(t["reload-delay"]);setTimeout((()=>{window.location.reload()}),e)}else window.location.reload()}else if(Object.prototype.hasOwnProperty.call(t,"toast")){const e=t.toast;(Array.isArray(e)?e:[e]).forEach((t=>{window.showToast(t)}))}else Object.prototype.hasOwnProperty.call(t,"error-toast")&&window.showToast(t["error-toast"])}(c)}}}))}}return t.default=p,t.getAllValidators=function(){return new Map(n)},t.getValidator=a,t.registerValidator=s,Object.defineProperty(t,"__esModule",{value:!0}),t}({});
1
+ var FormFather=function(t){"use strict";function e(t,e,i,o){return new(i||(i=Promise))((function(r,n){function s(t){try{l(o.next(t))}catch(t){n(t)}}function a(t){try{l(o.throw(t))}catch(t){n(t)}}function l(t){var e;t.done?r(t.value):(e=t.value,e instanceof i?e:new i((function(t){t(e)}))).then(s,a)}l((o=o.apply(t,e||[])).next())}))}function i(t){const e="FORM"===t.tagName?Array.from(t.elements):Array.from(t.querySelectorAll("input, select, textarea, button")),i=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++)i.append(`${e}[${t}]`,o[t])}else{const o=t.files;o&&o[0]&&i.append(e,o[0])}else{let r;if("select-one"===o||"select-multiple"===o){const n=t;if("select-multiple"===o){Array.from(n.selectedOptions).map((t=>t.value)).forEach(((t,o)=>{i.append(`${e}[${o}]`,t)}))}else r=n.value,r&&i.append(e,r)}else if("tel"===o)r=t.value.split(/[\s()-]/).join("").replace(/^8/,"+7");else if("checkbox"===o||"radio"===o){if(!t.checked)return;r=t.value}else if("date"===o){const e=t.getAttribute("data-date-format");r=e?function(t,e){const i=new Date(t),o=t=>t.toString().padStart(2,"0"),r=o(i.getDate()),n=o(i.getMonth()+1),s=i.getFullYear().toString();return e.replace("dd",r).replace("mm",n).replace("yyyy",s)}(t.value,e):t.value}else r=t.value;r&&"select-one"!==o&&"select-multiple"!==o&&i.append(e,r)}})),i}var o;"function"==typeof SuppressedError&&SuppressedError;const r=Symbol.for("FormFather.validators"),n=null!==(o=globalThis[r])&&void 0!==o?o:globalThis[r]=new Map;function s(t,e,i,{override:o=!1}={}){!n.has(t)||o?n.set(t,{fn:e,defaultMessage:i}):console.warn(`[FormFather] Validator "${t}" already exists; pass { override: true } to replace`)}const a=t=>n.get(t);var l;s("required",((t,e,i)=>{if(e&&e.type){if("checkbox"===e.type)return e.checked;if("radio"===e.type){const t=i.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)),"Неверный формат");const c=Symbol.for("formfather.shared"),d=null!==(l=globalThis[c])&&void 0!==l?l:globalThis[c]={defaultParams:{},defaultValidationSchema:void 0};let u=0;const p={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"]}};class h{static get defaultParams(){return d.defaultParams}static set defaultParams(t){d.defaultParams=t}static get defaultValidationSchema(){var t;return null!==(t=d.defaultValidationSchema)&&void 0!==t?t:d.defaultValidationSchema=p}static set defaultValidationSchema(t){d.defaultValidationSchema=t}constructor(t,i){this.$submits=[],this.waitResponse=!1,this.inputs=null,this._anim={duration:220,easing:"ease",paddingTopOpened:16,iconDuration:700},this.$el=t,this.options=i;this.config=Object.assign({},{onSubmit:()=>{},onResponse:()=>{},onResponseSuccess:()=>{},onResponseUnsuccess:()=>{},customTypeError:null,loaderColor:"#fff",showLoaderButton:!0,scrollToFirstErroredInput:!0,logging:!1,inputSelector:".input",inputWrapperSelector:".input-primary"},h.defaultParams,i),this.$el?(this.$submits=this.findSubmitElements(),this._onSubmitClickHandler=t=>e(this,void 0,void 0,(function*(){var e,i,o,r;t.preventDefault(),null===(i=(e=this.config).onBeforeValidate)||void 0===i||i.call(e,this);const n=yield this.validate();null===(r=(o=this.config).onAfterValidate)||void 0===r||r.call(o,n,this),n&&(yield this.submit())})),this.isCorrectArguments()&&(this.$submits.forEach((t=>{t.addEventListener("click",this._onSubmitClickHandler)})),this.initialization())):console.warn("Empty $el")}getOptions(){return this.options}static setDefaultParams(t){this.defaultParams=Object.assign(Object.assign({},this.defaultParams),t)}findSubmitElements(){return Array.from(this.$el.querySelectorAll('input[type="submit"], button[type="submit"]'))}initialization(){this.inputs=this.$el.querySelectorAll(this.config.inputSelector),this._onSubmitHandler=t=>e(this,void 0,void 0,(function*(){var e,i,o,r;t.preventDefault(),null===(i=(e=this.config).onBeforeValidate)||void 0===i||i.call(e,this);const n=yield this.validate();null===(r=(o=this.config).onAfterValidate)||void 0===r||r.call(o,n,this),n&&this.submit()})),this.$el.addEventListener("submit",this._onSubmitHandler)}showError(t,e){(function(t,e){if(null==t)return null;let i=t;for(;i;){if(i.matches(e))return i;i=i.parentElement}return null})(t,this.config.inputWrapperSelector).showError(e)}showLoader(){this.$submits.forEach((t=>{if(t.classList.add("button--loading"),t.querySelector(".button__loader"))return;const e="form-father-loader-"+u++,i=`\n\t\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\t<defs>\n\t\t\t\t\t<linearGradient id="${e}" x1="8.042%" x2="65.682%" y1="0%" y2="23.865%">\n\t\t\t\t\t\t<stop offset="0%" stop-color="${this.config.loaderColor}" stop-opacity="0"/>\n\t\t\t\t\t\t<stop offset="63.146%" stop-color="${this.config.loaderColor}" stop-opacity=".631"/>\n\t\t\t\t\t\t<stop offset="100%" stop-color="${this.config.loaderColor}"/>\n\t\t\t\t\t</linearGradient>\n\t\t\t\t\t</defs>\n\t\t\t\t\t<g fill-rule="evenodd" fill="none">\n\t\t\t\t\t<g transform="translate(1 1)">\n\t\t\t\t\t\t<path d="M36 18c0-9.94-8.06-18-18-18" id="Oval-2" stroke-width="5" stroke="url(#${e})"></path>\n\t\t\t\t\t\t<circle cx="36" cy="18" fill="${this.config.loaderColor}" r="1"></circle>\n\t\t\t\t\t</g>\n\t\t\t\t\t</g>\n\t\t\t\t</svg>\n\t\t\t`,o=document.createElement("span");o.innerHTML=i,o.className="button__loader",t.insertAdjacentElement("afterbegin",o),requestAnimationFrame((()=>{o.setAttribute("data-showed","")}))}))}hideLoader(){this.$submits.forEach((t=>{t.classList.remove("button--loading");const e=t.querySelector(".button__loader");e&&(e.classList.remove("active"),e.removeAttribute("data-showed"),setTimeout((()=>{e.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 i=null,o=1/0;if(t.forEach((t=>{const r=e.findIndex((e=>e===t));r<o&&(o=r,i=t)})),i){const t=i.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,arguments,void 0,(function*(t=this.$el){const i=Object.assign(Object.assign({},h.defaultValidationSchema||{}),this.config.validationSchema||{}),o=t=>console.warn(`[FormFather] Unknown validation rule "${t}"`),r=[],n=new WeakSet;let s=!0;const l=(t,e=[])=>{var i;const r=[];t.hasAttribute("required")&&r.push("required"),r.push(...e);const n=(null!==(i=t.getAttribute("data-custom-validate"))&&void 0!==i?i:"").split(",").map((t=>t.trim())).filter(Boolean);r.push(...n);const s=[];for(const t of r){const e="string"==typeof t?t:t.rule;a(e)?s.push(t):o(e)}return s},c=(i,o,...n)=>e(this,[i,o,...n],void 0,(function*(e,i,o={}){if(e.hasAttribute("data-no-validate"))return;if(!("checkbox"===e.type||"radio"===e.type?!e.checked:0===e.value.trim().length)||i.includes("required")){for(const n of i){const{rule:i,params:l}="string"==typeof n?{rule:n,params:void 0}:n,c=a(i),d=yield c.fn(e.value,e,t,l),u="object"==typeof d&&null!==d,p=u?!0===d.valid:!!d;if(u&&d.effect&&(yield d.effect({value:e.value,$input:e,$form:t,params:l})),!p){s=!1;const t=d,n=u&&"string"==typeof t.message&&t.message||o[i]||c.defaultMessage;return this.showError(e,n),void r.push(e)}if(u&&d.stopOthers)return}this.hideError(e)}else this.hideError(e)}));for(const[e,o]of Object.entries(i)){const{selector:i,rules:r=[],messages:s={}}=o,a=i?t.querySelectorAll(i):t.querySelectorAll(`[data-validate="${e}"]`);for(const t of Array.from(a))n.has(t)||(n.add(t),yield c(t,l(t,r),s))}const d=Array.from(t.querySelectorAll("[data-custom-validate]")).filter((t=>!n.has(t)));for(const t of d)n.add(t),yield c(t,l(t,[]));return!s&&this.config.scrollToFirstErroredInput&&this.scrollToFirstErroredInput(r.filter((t=>!t.hasAttribute("data-no-error-scroll")))),s}))}disableSubmit(){this.$submits.forEach((t=>{t.setAttribute("disabled","")}))}enableSubmit(){this.$submits.forEach((t=>{t.removeAttribute("disabled")}))}clearInputs(){var t;null===(t=this.inputs)||void 0===t||t.forEach((t=>{var e;const i=t;"radio"===i.type||"checkbox"===i.type?i.checked=!1:(i.value="",null===(e=i.parentElement)||void 0===e||e.classList.remove("filled"),i.dispatchEvent(new Event("input")))}))}_prefersReducedMotion(){var t;return"undefined"!=typeof window&&(null===(t=window.matchMedia)||void 0===t?void 0:t.call(window,"(prefers-reduced-motion: reduce)").matches)}_canAnimate(t){return!(!t||!("animate"in t)||this._prefersReducedMotion())}_cancelAnimations(t){var e;null===(e=null==t?void 0:t.getAnimations)||void 0===e||e.call(t).forEach((t=>t.cancel()))}showErrorForm(t){var e;const i=this.$el.querySelectorAll(this.config.inputWrapperSelector),o=i[i.length-1];let r=this.$el.querySelector(".error-block-under-input__wrapper");r&&o.nextElementSibling===r?(r.style.boxSizing="border-box",r.style.overflow="hidden"):(r=document.createElement("div"),r.className="error-block-under-input__wrapper",r.innerHTML='\n <div class="error-block-under-input error-block-under-input--warning" style="display:grid;grid-template-columns:auto 1fr;gap:8px;align-items:start;">\n <div class="error-block-under-input__icon-wrapper" style="position:relative;width:20px;height:20px;">\n <span class="error-block-under-input__icon" style="display:block;width:20px;height:20px;"></span>\n <span class="error-block-under-input__icon error-block-under-input__icon--animated" style="display:block;position:absolute;inset:0;"></span>\n </div>\n <p class="error-block-under-input__text" style="margin:0;">\n <span class="error-block-under-input__main-text"></span>\n <span class="error-block-under-input__secondary-text"></span>\n </p>\n </div>\n ',Object.assign(r.style,{boxSizing:"border-box",overflow:"hidden",height:"0px",paddingTop:"0px",opacity:"0"}),o.insertAdjacentElement("afterend",r)),r.querySelector(".error-block-under-input__main-text").textContent=t;const n=r.querySelector(".error-block-under-input__secondary-text");n&&(n.textContent=""),null===(e=r.querySelector(".error-block-under-input"))||void 0===e||e.classList.remove("error-block-under-input--success"),r.querySelector(".error-block-under-input");const s=r.style.height,a=r.style.paddingTop;r.style.height="auto",r.style.paddingTop=`${this._anim.paddingTopOpened}px`;const l=r.clientHeight;if(r.style.height=s||"0px",r.style.paddingTop=a||"0px",parseFloat(r.style.height)===l&&1===parseFloat(r.style.opacity||"1"))this._ringIcon(r);else{if(this._cancelAnimations(r),this._canAnimate(r)){r.animate([{height:`${parseFloat(r.style.height)||0}px`,paddingTop:`${parseFloat(r.style.paddingTop)||0}px`,opacity:parseFloat(r.style.opacity||"0")},{height:`${l}px`,paddingTop:`${this._anim.paddingTopOpened}px`,opacity:1}],{duration:this._anim.duration,easing:this._anim.easing,fill:"forwards"}).addEventListener("finish",(()=>{r.style.height="auto",r.style.paddingTop=`${this._anim.paddingTopOpened}px`,r.style.opacity="1"}))}else r.style.height="auto",r.style.paddingTop=`${this._anim.paddingTopOpened}px`,r.style.opacity="1";this._ringIcon(r)}this.$el.addEventListener("input",(()=>this.hideErrorForm()),{passive:!0,once:!0})}hideErrorForm(){const t=this.$el.querySelectorAll(this.config.inputWrapperSelector),e=t[t.length-1].nextElementSibling;if(!e||!e.classList.contains("error-block-under-input__wrapper"))return;if((""===e.style.height||"auto"===e.style.height)&&(e.style.height=`${e.clientHeight}px`),e.style.paddingTop=e.style.paddingTop||`${this._anim.paddingTopOpened}px`,e.style.opacity=e.style.opacity||"1",this._cancelAnimations(e),this._canAnimate(e)){e.animate([{height:`${parseFloat(e.style.height)||e.clientHeight}px`,paddingTop:`${parseFloat(e.style.paddingTop)||this._anim.paddingTopOpened}px`,opacity:parseFloat(e.style.opacity||"1")},{height:"0px",paddingTop:"0px",opacity:0}],{duration:this._anim.duration,easing:this._anim.easing,fill:"forwards"}).addEventListener("finish",(()=>{e.remove()}))}else e.remove()}_ringIcon(t){const e=t.querySelector(".error-block-under-input__icon--animated");e&&(this._cancelAnimations(e),this._canAnimate(e)&&e.animate([{transform:"rotate(0deg) scale(1)",opacity:0},{transform:"rotate(-8deg) scale(1.05)",opacity:1,offset:.15},{transform:"rotate(8deg) scale(1.05)",opacity:1,offset:.3},{transform:"rotate(-6deg) scale(1.03)",opacity:1,offset:.45},{transform:"rotate(6deg) scale(1.03)",opacity:1,offset:.6},{transform:"rotate(0deg) scale(1)",opacity:0}],{duration:this._anim.iconDuration,easing:"ease"}))}destroy(){this._onSubmitHandler&&(this.$el.removeEventListener("submit",this._onSubmitHandler),this._onSubmitHandler=void 0),this._onSubmitClickHandler&&(this.$submits.forEach((t=>{t.removeEventListener("click",this._onSubmitClickHandler)})),this._onSubmitClickHandler=void 0);const t=this.$el.querySelector(".error-block-under-input__wrapper");t&&(this._cancelAnimations(t),t.remove()),this.$submits.forEach((t=>{t.classList.remove("button--loading");const e=t.querySelector(".button__loader");e&&e.remove()}));this.$el.querySelectorAll("input, textarea").forEach((t=>{t instanceof HTMLInputElement&&this.hideError(t)})),document.documentElement.removeAttribute("data-now-scrolling"),this.inputs=null,this.$submits=[],this.waitResponse=!1}isCorrectArguments(){return"FORM"!==this.$el.tagName?(console.warn("$el не является тегом form"),!1):0!==this.$submits.length||(console.warn("В форме нет кнопки с типом submit"),!1)}sendData(){return 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",r=this.$el.getAttribute("enctype")||"application/x-www-form-urlencoded";let n=null,s={};const a=i(this.$el);let l={};if(a.forEach(((t,e)=>{l[e]=t})),this.config.logging)for(const t of a.keys())console.log(a.get(t));switch("function"==typeof this.config.wrapData&&(l=this.config.wrapData(l)),r){case"application/x-www-form-urlencoded":n=new URLSearchParams(i(this.$el)).toString(),s["Content-Type"]="application/x-www-form-urlencoded";break;case"multipart/form-data":n=i(this.$el);break;case"text/plain":n=Array.from(i(this.$el)).map((([t,e])=>`${encodeURIComponent(t)}=${encodeURIComponent(e)}`)).join("\n"),s["Content-Type"]="text/plain";break;case"application/json":n=JSON.stringify(l),s["Content-Type"]="application/json";break;default:console.warn(`Неизвестный enctype: ${r}. Используется application/x-www-form-urlencoded.`),n=new URLSearchParams(i(this.$el)).toString(),s["Content-Type"]="application/x-www-form-urlencoded"}return fetch(e,{method:o,body:n,headers:s})}))}submit(){return e(this,void 0,void 0,(function*(){var t,e,i,o,r,n,s,a;if(!this.waitResponse){!0===this.config.showLoaderButton&&this.showLoader(),null===(e=(t=this.config).onSubmit)||void 0===e||e.call(t,this),this.waitResponse=!0;const l=yield this.sendData(),c=yield l.json();if(this.waitResponse=!1,!0===this.config.showLoaderButton&&this.hideLoader(),null===(o=(i=this.config).onResponse)||void 0===o||o.call(i,c,this),200===l.status){if(!0===c.success)null===(n=(r=this.config).onResponseSuccess)||void 0===n||n.call(r,c,this);else if(null===(a=(s=this.config).onResponseUnsuccess)||void 0===a||a.call(s,c,this),!0===c.error&&(c["error-msg"]&&this.showErrorForm(c["error-msg"]),c.errors)){const t=[];c.errors.forEach((e=>{const i=this.$el.querySelector(`input[name="${e.name}"]`);i?(t.push(i),this.showError(i,e["error-msg"])):console.warn(`Не найдено поле с именем: ${e.name}, для вывода ошибки: ${e["error-msg"]}`)})),!0===this.config.scrollToFirstErroredInput&&this.scrollToFirstErroredInput(t)}!function(t){if(Object.prototype.hasOwnProperty.call(t,"redirect-url"))if(t["redirect-url-delay"]){const e=Number(t["redirect-url-delay"]);setTimeout((()=>{window.location.href=t["redirect-url"]}),e)}else window.location.href=t["redirect-url"];else if(Object.prototype.hasOwnProperty.call(t,"reload")){if(!0===t.reload)if(t["reload-delay"]){const e=Number(t["reload-delay"]);setTimeout((()=>{window.location.reload()}),e)}else window.location.reload()}else if(Object.prototype.hasOwnProperty.call(t,"toast")){const e=t.toast;(Array.isArray(e)?e:[e]).forEach((t=>{window.showToast(t)}))}else Object.prototype.hasOwnProperty.call(t,"error-toast")&&window.showToast(t["error-toast"])}(c)}}}))}}return t.default=h,t.getAllValidators=function(){return new Map(n)},t.getValidator=a,t.registerValidator=s,Object.defineProperty(t,"__esModule",{value:!0}),t}({});
2
2
  //# sourceMappingURL=FormFather.min.js.map
package/index.d.ts CHANGED
@@ -105,7 +105,7 @@ declare class Form {
105
105
  $el: HTMLFormElement;
106
106
  private options;
107
107
  private config;
108
- private $submit;
108
+ private $submits;
109
109
  private waitResponse;
110
110
  private inputs;
111
111
  private _onSubmitHandler?;
@@ -130,6 +130,7 @@ declare class Form {
130
130
  * свойства, которые необходимо обновить; остальные сохранятся без изменений.
131
131
  */
132
132
  static setDefaultParams(params: Partial<FormOptions>): void;
133
+ private findSubmitElements;
133
134
  private initialization;
134
135
  /**
135
136
  * Показывает ошибку для поля ввода.
package/index.js CHANGED
@@ -246,6 +246,7 @@ const __shared =
246
246
  defaultParams: {},
247
247
  defaultValidationSchema: undefined,
248
248
  });
249
+ let loaderIdCounter = 0;
249
250
  /** Изначальная дефолтная схема. */
250
251
  const INITIAL_DEFAULT_SCHEMA = {
251
252
  tel: {
@@ -295,8 +296,7 @@ class Form {
295
296
  * @param {Object} options - Параметры формы.
296
297
  */
297
298
  constructor($el, options) {
298
- var _a;
299
- this.$submit = null;
299
+ this.$submits = [];
300
300
  this.waitResponse = false;
301
301
  this.inputs = null;
302
302
  /** Общие настройки анимаций (можно подправить под вкус) */
@@ -324,7 +324,7 @@ class Form {
324
324
  /* Слияние параметров: глобальные параметры → пользовательские параметры */
325
325
  this.config = Object.assign({}, defaultConfig, Form.defaultParams, options);
326
326
  if (this.$el) {
327
- this.$submit = this.$el.querySelector('input[type="submit"], button[type="submit"]');
327
+ this.$submits = this.findSubmitElements();
328
328
  this._onSubmitClickHandler = (e) => __awaiter(this, void 0, void 0, function* () {
329
329
  var _a, _b, _c, _d;
330
330
  e.preventDefault();
@@ -335,9 +335,12 @@ class Form {
335
335
  yield this.submit();
336
336
  }
337
337
  });
338
- (_a = this.$submit) === null || _a === void 0 ? void 0 : _a.addEventListener('click', this._onSubmitClickHandler);
339
- if (this.isCorrectArguments())
338
+ if (this.isCorrectArguments()) {
339
+ this.$submits.forEach($submit => {
340
+ $submit.addEventListener('click', this._onSubmitClickHandler);
341
+ });
340
342
  this.initialization();
343
+ }
341
344
  }
342
345
  else {
343
346
  console.warn('Empty $el');
@@ -356,6 +359,9 @@ class Form {
356
359
  static setDefaultParams(params) {
357
360
  this.defaultParams = Object.assign(Object.assign({}, this.defaultParams), params);
358
361
  }
362
+ findSubmitElements() {
363
+ return Array.from(this.$el.querySelectorAll('input[type="submit"], button[type="submit"]'));
364
+ }
359
365
  initialization() {
360
366
  this.inputs = this.$el.querySelectorAll(this.config.inputSelector);
361
367
  /* TODO: Добавить параметр с возможностью отключать/включать кнопку, в зависимости от валидности поля. */
@@ -390,46 +396,50 @@ class Form {
390
396
  }
391
397
  /** Показывает лоадер */
392
398
  showLoader() {
393
- var _a;
394
- // Создаем SVG элемент
395
- const loaderSvg = `
396
- <svg height="38" viewBox="0 0 38 38" width="38" xmlns="http://www.w3.org/2000/svg">
397
- <defs>
398
- <linearGradient id="form-father-loader" x1="8.042%" x2="65.682%" y1="0%" y2="23.865%">
399
- <stop offset="0%" stop-color="${this.config.loaderColor}" stop-opacity="0"/>
400
- <stop offset="63.146%" stop-color="${this.config.loaderColor}" stop-opacity=".631"/>
401
- <stop offset="100%" stop-color="${this.config.loaderColor}"/>
402
- </linearGradient>
403
- </defs>
404
- <g fill-rule="evenodd" fill="none">
405
- <g transform="translate(1 1)">
406
- <path d="M36 18c0-9.94-8.06-18-18-18" id="Oval-2" stroke-width="5" stroke="url(#form-father-loader)"></path>
407
- <circle cx="36" cy="18" fill="${this.config.loaderColor}" r="1"></circle>
408
- </g>
409
- </g>
410
- </svg>
411
- `;
412
- // Создаем элемент загрузчика и добавляем SVG внутрь
413
- const $loaderEl = document.createElement('span');
414
- $loaderEl.innerHTML = loaderSvg;
415
- $loaderEl.className = 'button__loader';
416
- (_a = this.$submit) === null || _a === void 0 ? void 0 : _a.insertAdjacentElement('afterbegin', $loaderEl);
417
- requestAnimationFrame(() => {
418
- $loaderEl.setAttribute('data-showed', '');
399
+ this.$submits.forEach($submit => {
400
+ $submit.classList.add('button--loading');
401
+ if ($submit.querySelector('.button__loader'))
402
+ return;
403
+ const gradientId = `form-father-loader-${loaderIdCounter++}`;
404
+ const loaderSvg = `
405
+ <svg height="38" viewBox="0 0 38 38" width="38" xmlns="http://www.w3.org/2000/svg">
406
+ <defs>
407
+ <linearGradient id="${gradientId}" x1="8.042%" x2="65.682%" y1="0%" y2="23.865%">
408
+ <stop offset="0%" stop-color="${this.config.loaderColor}" stop-opacity="0"/>
409
+ <stop offset="63.146%" stop-color="${this.config.loaderColor}" stop-opacity=".631"/>
410
+ <stop offset="100%" stop-color="${this.config.loaderColor}"/>
411
+ </linearGradient>
412
+ </defs>
413
+ <g fill-rule="evenodd" fill="none">
414
+ <g transform="translate(1 1)">
415
+ <path d="M36 18c0-9.94-8.06-18-18-18" id="Oval-2" stroke-width="5" stroke="url(#${gradientId})"></path>
416
+ <circle cx="36" cy="18" fill="${this.config.loaderColor}" r="1"></circle>
417
+ </g>
418
+ </g>
419
+ </svg>
420
+ `;
421
+ const $loaderEl = document.createElement('span');
422
+ $loaderEl.innerHTML = loaderSvg;
423
+ $loaderEl.className = 'button__loader';
424
+ $submit.insertAdjacentElement('afterbegin', $loaderEl);
425
+ requestAnimationFrame(() => {
426
+ $loaderEl.setAttribute('data-showed', '');
427
+ });
419
428
  });
420
429
  }
421
430
  /** Скрывает лоадер */
422
431
  hideLoader() {
423
- var _a, _b;
424
- (_a = this.$submit) === null || _a === void 0 ? void 0 : _a.classList.remove('button--loading');
425
- const $loader = (_b = this.$submit) === null || _b === void 0 ? void 0 : _b.querySelector('.button__loader');
426
- if ($loader) {
427
- $loader.classList.remove('active');
428
- $loader.removeAttribute('data-showed');
429
- setTimeout(() => {
430
- $loader.remove();
431
- }, 250);
432
- }
432
+ this.$submits.forEach($submit => {
433
+ $submit.classList.remove('button--loading');
434
+ const $loader = $submit.querySelector('.button__loader');
435
+ if ($loader) {
436
+ $loader.classList.remove('active');
437
+ $loader.removeAttribute('data-showed');
438
+ setTimeout(() => {
439
+ $loader.remove();
440
+ }, 250);
441
+ }
442
+ });
433
443
  }
434
444
  /**
435
445
  * Скрывает ошибку.
@@ -585,13 +595,15 @@ class Form {
585
595
  }
586
596
  /** Блокирует кнопку отправки данных. */
587
597
  disableSubmit() {
588
- var _a;
589
- (_a = this.$submit) === null || _a === void 0 ? void 0 : _a.setAttribute('disabled', '');
598
+ this.$submits.forEach($submit => {
599
+ $submit.setAttribute('disabled', '');
600
+ });
590
601
  }
591
602
  /** Снимает блокировку с кнопки отправки данных. */
592
603
  enableSubmit() {
593
- var _a;
594
- (_a = this.$submit) === null || _a === void 0 ? void 0 : _a.removeAttribute('disabled');
604
+ this.$submits.forEach($submit => {
605
+ $submit.removeAttribute('disabled');
606
+ });
595
607
  }
596
608
  /** Очищает поля ввода формы. */
597
609
  clearInputs() {
@@ -778,7 +790,6 @@ class Form {
778
790
  }
779
791
  /** Полностью снимает слушатели и чистит артефакты формы. */
780
792
  destroy() {
781
- var _a, _b, _c;
782
793
  // 1) Снять submit-слушатель
783
794
  if (this._onSubmitHandler) {
784
795
  this.$el.removeEventListener('submit', this._onSubmitHandler);
@@ -786,7 +797,9 @@ class Form {
786
797
  }
787
798
  // 1.1) Снять click-слушатель с кнопки submit
788
799
  if (this._onSubmitClickHandler) {
789
- (_a = this.$submit) === null || _a === void 0 ? void 0 : _a.removeEventListener('click', this._onSubmitClickHandler);
800
+ this.$submits.forEach($submit => {
801
+ $submit.removeEventListener('click', this._onSubmitClickHandler);
802
+ });
790
803
  this._onSubmitClickHandler = undefined;
791
804
  }
792
805
  // 2) Удалить формовый error-блок под инпутами (если есть)
@@ -796,10 +809,12 @@ class Form {
796
809
  formErrorWrapper.remove();
797
810
  }
798
811
  // 3) Скрыть/удалить лоадер на кнопке submit
799
- (_b = this.$submit) === null || _b === void 0 ? void 0 : _b.classList.remove('button--loading');
800
- const btnLoader = (_c = this.$submit) === null || _c === void 0 ? void 0 : _c.querySelector('.button__loader');
801
- if (btnLoader)
802
- btnLoader.remove();
812
+ this.$submits.forEach($submit => {
813
+ $submit.classList.remove('button--loading');
814
+ const btnLoader = $submit.querySelector('.button__loader');
815
+ if (btnLoader)
816
+ btnLoader.remove();
817
+ });
803
818
  // 4) Сбросить ошибки у инпутов (если разметка позволяет)
804
819
  const inputs = this.$el.querySelectorAll('input, textarea');
805
820
  inputs.forEach($i => {
@@ -810,7 +825,7 @@ class Form {
810
825
  document.documentElement.removeAttribute('data-now-scrolling');
811
826
  // 6) Очистить ссылки на элементы, чтобы помочь GC
812
827
  this.inputs = null;
813
- this.$submit = null;
828
+ this.$submits = [];
814
829
  this.waitResponse = false;
815
830
  }
816
831
  /**
@@ -823,7 +838,7 @@ class Form {
823
838
  console.warn(`$el не является тегом form`);
824
839
  return false;
825
840
  }
826
- if (!this.$submit) {
841
+ if (this.$submits.length === 0) {
827
842
  console.warn(`В форме нет кнопки с типом submit`);
828
843
  return false;
829
844
  }
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "form-father",
3
- "version": "0.2.7",
3
+ "version": "0.2.8",
4
4
  "description": "Form Father: Библиотека для обработки форм",
5
5
  "type": "module",
6
6
  "scripts": {
package/types/index.d.ts CHANGED
@@ -80,7 +80,7 @@ export default class Form {
80
80
  $el: HTMLFormElement;
81
81
  private options;
82
82
  private config;
83
- private $submit;
83
+ private $submits;
84
84
  private waitResponse;
85
85
  private inputs;
86
86
  private _onSubmitHandler?;
@@ -105,6 +105,7 @@ export default class Form {
105
105
  * свойства, которые необходимо обновить; остальные сохранятся без изменений.
106
106
  */
107
107
  static setDefaultParams(params: Partial<FormOptions>): void;
108
+ private findSubmitElements;
108
109
  private initialization;
109
110
  /**
110
111
  * Показывает ошибку для поля ввода.