1(function () { 2 if (typeof BX.wms === 'undefined') { 3 BX.wms = {}; 4 } 5 if (typeof BX.wms.forms === 'undefined') { 6 BX.wms.forms = {}; 7 } 8 9 BX.wms.forms.contactsForm = { 10 name: 'contactsForm', 11 components: { 12 CitySuggestInput: BX.wms.forms.CitySuggestInput 13 }, 14 props: { 15 dadataKey: {type: String, default: ''}, 16 userId: {type: [String, Number], default: ''}, 17 yandexSiteKey: {type: String, default: ''}, 18 captchaResetKey: { 19 type: [String, Number], 20 default: () => Date.now() 21 }, 22 errors: { 23 type: Object, 24 default: () => ({}) 25 } 26 }, 27 data() { 28 return { 29 name: '', 30 email: '', 31 phone: '', 32 city: '', 33 message: '', 34 subject: '', 35 agreement: false, 36 successSent: false, 37 errorSent: false, 38 serverError: false, 39 useYandexCaptcha: true, 40 smartToken: null, 41 phoneMaskInstance: null, 42 }; 43 }, 44 watch: { 45 errors: { 46 handler(newErrors) { 47 if (!this.$el) return; 48 49 this.clearAllErrors(); 50 const captchaContainer = this.$el.querySelector('.form-captcha-container'); 51 if (captchaContainer) { 52 captchaContainer.classList.remove('error'); 53 } 54 55 if (!newErrors || typeof newErrors !== 'object') return; 56 57 Object.keys(newErrors).forEach(fieldName => { 58 if (fieldName === 'smartToken') { 59 if (captchaContainer) { 60 captchaContainer.classList.add('error'); 61 } 62 } else { 63 const input = this.$el.querySelector(`[name="${fieldName}"]`); 64 if (input) { 65 input.classList.add('error'); 66 } 67 } 68 }); 69 }, 70 deep: true, 71 immediate: true 72 } 73 }, 74 mounted() { 75 if (BX.wms.forms.FormPersistence) { 76 BX.wms.forms.FormPersistence.initFormPersistence.call(this); 77 } 78 const phoneInput = this.$el.querySelector('.phone'); 79 if (phoneInput && window.Inputmask) { 80 const mask = new window.Inputmask('+7 (999) 999-99-99', { 81 showMaskOnHover: false, 82 showMaskOnFocus: true, 83 clearIncomplete: true, 84 autoUnmask: false 85 }); 86 mask.mask(phoneInput); 87 this.phoneMaskInstance = mask; 88 } 89 90 if (this.$el) this.$el.querySelectorAll('.input').forEach(input => { 91 input.addEventListener('input', () => input.classList.remove('error')); 92 }); 93 94 // ÐниÑиализаÑÐ¸Ñ Ð¿Ð¾Ð»Ñ Ð³Ð¾Ñода 95 if (window.BX && window.BX.Suggest) { 96 new window.BX.Suggest('cities-list', function (value) { 97 this.value = value; 98 this.dispatchEvent(new Event('input')); 99 }.bind(this.$el.querySelector('#city-field'))); 100 } 101 }, 102 beforeUnmount() { 103 if (this.phoneMaskInstance) { 104 this.phoneMaskInstance.remove(); 105 } 106 }, 107 methods: { 108 validateForm() { 109 this.clearAllErrors(); 110 let isValid = true; 111 112 if (!this.name.trim()) { 113 this.setError('name'); 114 isValid = false; 115 } 116 117 if (!this.email || !/^\S+@\S+\.\S+$/.test(this.email)) { 118 this.setError('email'); 119 isValid = false;
120 } 121 122 const phoneDigits = this.phone.replace(/\D/g, ''); 123 if (!this.phone || !/^(7|8)\d{10}$/.test(phoneDigits)) { 124 this.setError('phone'); 125 isValid = false; 126 } 127 128 if (!this.agreement) { 129 this.setError('agreement'); 130 isValid = false; 131 } 132 133 return isValid; 134 }, 135 setError(fieldName) { 136 const fieldMap = { 137 name: '#name-field', 138 phone: '#phone-field', 139 email: '#email-field', 140 agreement: '#contact-consent' 141 }; 142 const selector = fieldMap[fieldName]; 143 if (!selector) return; 144 145 const el = this.$el.querySelector(selector); 146 if (!el) return; 147 148 el.classList.add('error'); 149 150 }, 151 clearAllErrors() { 152 if (!this.$el) return; 153 this.$el.querySelectorAll('.input.error, textarea.error').forEach(el => { 154 el.classList.remove('error'); 155 }); 156 this.$el.querySelectorAll('.checkboxEl.error').forEach(el => { 157 el.classList.remove('error'); 158 }); 159 }, 160 async submitForm() { 161 if (!this.validateForm()) { 162 this.errorSent = true; 163 return; 164 } 165 166 let data = { 167 name: this.name, 168 email: this.email, 169 phone: this.phone, 170 city: this.city, 171 smartToken: this.smartToken 172 }; 173 try { 174 await this.$emit('submit', data); 175 // this.successSent = true; 176 //this.resetForm(); 177 } catch (e) { 178 this.errorSent = true; 179 this.serverError = true; 180 } 181 }, 182 handleTokenUpdate(token) { 183 this.smartToken = token; 184 this.errorSent = false; 185 }, 186 resetForm() { 187 this.name = ''; 188 this.email = ''; 189 this.phone = ''; 190 this.city = ''; 191 this.message = ''; 192 this.subject = ''; 193 this.agreement = false; 194 this.smartToken = null; 195 }, 196 resetAll() { 197 this.resetForm(); // СбÑаÑÑваем Ð¿Ð¾Ð»Ñ 198 this.successSent = false; // СкÑÑваем окно ÑÑÐ¿ÐµÑ Ð° 199 }, 200 }, 201 computed: { 202 isLoggedIn() { 203 return this.userId && Number(this.userId) > 0; 204 } 205 }, 206 template: ` 207 <div> 208 <h2>ÐÑ Ð½Ð° ÑвÑзи</h2> 209 <p>ÐÑÑавÑÑе заÑвкÑ, и Ð¼Ñ ÑвÑжемÑÑ Ñ Ð²Ð°Ð¼Ð¸</p> 210 <form id="contactForm" class="turqForm contactForm saveState " @submit.prevent="submitForm"> 211 212 <div class="input-wrap" :class="{ error: !!errors.name }"> 213 <input 214 placeholder="ÐаÑе имÑ" 215 type="text" 216 class="input" 217 name="name" 218 id="name-field" 219 v-model="name" 220 @input="$event.target.classList.remove('error')" 221 > 222 </div> 223 224 <div class="input-wrap" :class="{ error: !!errors.phone }"> 225 <input 226 placeholder="+7 (___)-___-__-__" 227 type="text" 228 name="phone" 229 class="input phone" 230 id="phone-field" 231 v-model="phone" 232 @input="$event.target.classList.remove('error')" 233 > 234 </div> 235 236 <div class="input-wrap" :class="{ error: !!errors.email }"> 237 <input 238 placeholder="E-mail" 239 type="text" 240 name="email" 241 class="input" 242 id="email-field" 243 v-model="email"
244 @input="$event.target.classList.remove('error')" 245 > 246 </div> 247 248 <div class="input-wrap"> 249 <city-suggest-input 250 v-model="city" 251 placeholder="ÐоÑод" 252 :dadata-key="dadataKey" 253 @select="onCitySelect" 254 /> 255 </div> 256 257 <div class="wrapBox"> 258 <div class="checkboxEl vue-consent input-wrap"> 259 <input id="contact-consent" type="checkbox" v-model="agreement" name="agreement" required> 260 <label for="contact-consent"> 261 <span class="agreement-box box" style="pointer-events: none"></span> 262 Я ÑоглаÑен на <a href="/politika-konfidentsialnosti/">обÑабоÑÐºÑ ÑÐ²Ð¾Ð¸Ñ Ð¿ÐµÑÑоналÑнÑÑ Ð´Ð°Ð½Ð½ÑÑ .</a> 263 </label> 264 </div> 265 </div> 266 <div class="wrapBox"> 267 <div v-if="useYandexCaptcha" 268 class="form-captcha-container" 269 @click="removeCaptchaError" 270 id="yandex-captcha-container" 271 > 272 <yandex-captcha 273 :key="captchaResetKey" 274 :site-key="yandexSiteKey" 275 size="compact" 276 theme="light" 277 @update:model-value="handleTokenUpdate" 278 /> 279 </div> 280 </div> 281 282 283 <div class="wrapBox wrapBtn"> 284 <input 285 type="button" 286 @click="submitForm" 287 name="web_form_submit" 288 class="btn green" 289 :value="successSent ? 'ÐÑпÑавлено!' : 'ÐÑпÑавиÑÑ Ð·Ð°ÑвкÑ'" 290 :disabled="successSent" 291 > 292 293 294 <p class="tipText sucess_res" v-show="successSent"> 295 <span class="text-box"> 296 ÐаÑа заÑвка ÑÑпеÑно оÑпÑавлена! 297 </span> 298 <input 299 type="button" 300 @click="resetAll" 301 class="btn green" 302 :value="'ÐÑлиÑно'" 303 > 304 </p> 305 <p class="tipText error_res " v-show="errorSent && !serverError"> 306 <span class="errorFormRedBg"> 307 <i class="error-ic ic"></i> ÐÑовеÑÑÑе пÑавилÑноÑÑÑ Ð²Ð²Ð¾Ð´Ð° даннÑÑ 308 </span> 309 310 </p> 311 <p class="tipText error_res" v-show="errorSent && serverError"> 312 <span class="errorFormRedBg"> 313 <i class="error-ic ic"></i> ÐÑибка на ÑеÑвеÑе. ÐовÑоÑиÑе попÑÑÐºÑ Ð¿Ð¾Ð·Ð¶Ðµ. 314 </span> 315 </p> 316 </div> 317 </form> 318 </div> 319` 320 }; 321})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.