1(function () { 2 if (window.consultWidgetInited) { 3 return; 4 } 5 window.consultWidgetInited = true; 6 7 function start($) { 8 var YM_ID = 40834834; 9 var MAX_FILES = 5; 10 var MAX_SIZE = 10 * 1024 * 1024; 11 var ALLOWED_EXT = ['doc', 'docx', 'pdf', 'xls', 'xlsx', 'png', 'jpg', 'jpeg']; 12 var PLACEHOLDERS = { 13 mail: '[email protected]', 14 phone: '+7 (___) ___-__-__', 15 max: 'ÐÐ¾Ð¼ÐµÑ Ð² MAX +7 (___) ___-__-__' 16 }; 17 18 var FILE_NAME_MAX = 32; 19 var selectedFiles = []; 20 var contactMask = null; 21 var $widget; 22 var $overlay; 23 var $popup; 24 var $form; 25 var $contact; 26 var $channelInput; 27 var $fileInput; 28 var $fileStatus; 29 var $fileList; 30 var $submit; 31 32 function reachGoal(name) { 33 if (typeof ym === 'function') { 34 try { 35 ym(YM_ID, 'reachGoal', name); 36 } catch (e) {} 37 } 38 } 39 40 function phoneMask() { 41 if (window.arTires2Options && arTires2Options.THEME && arTires2Options.THEME.PHONE_MASK) { 42 return arTires2Options.THEME.PHONE_MASK; 43 } 44 return '+7 (999) 999-99-99'; 45 } 46 47 function hasInputmask() { 48 return !!(window.jQuery && $.fn && $.fn.inputmask); 49 } 50 51 function destroyMask() { 52 if (contactMask && typeof contactMask.destroy === 'function') { 53 contactMask.destroy(); 54 contactMask = null; 55 } 56 if ($contact && $contact.length && hasInputmask()) { 57 try { 58 $contact.inputmask('remove'); 59 } catch (e) {} 60 } 61 if ($contact && $contact.length) { 62 $contact.off('input.consultPhoneMask'); 63 } 64 } 65 66 function formatPhoneFallback(value) { 67 var digits = String(value || '').replace(/\D+/g, ''); 68 if (digits.charAt(0) === '8') { 69 digits = '7' + digits.slice(1); 70 } 71 if (digits.charAt(0) !== '7') { 72 digits = '7' + digits; 73 } 74 digits = digits.slice(0, 11); 75 var rest = digits.slice(1); 76 var out = '+7'; 77 if (rest.length) { 78 out += ' (' + rest.slice(0, 3); 79 } 80 if (rest.length >= 3) { 81 out += ')'; 82 } 83 if (rest.length > 3) { 84 out += ' ' + rest.slice(3, 6); 85 } 86 if (rest.length > 6) { 87 out += '-' + rest.slice(6, 8); 88 } 89 if (rest.length > 8) { 90 out += '-' + rest.slice(8, 10); 91 } 92 return out; 93 } 94 95 function applyMask(channel) { 96 destroyMask(); 97 if (!$contact || !$contact.length) { 98 return; 99 } 100 $contact.toggleClass('phone', channel === 'phone' || channel === 'max'); 101 if (channel !== 'phone' && channel !== 'max') { 102 return; 103 } 104 105 var el = $contact.get(0); 106 if (window.IMask && el) { 107 contactMask = window.IMask(el, { 108 mask: '+{7} (000) 000-00-00', 109 lazy: false, 110 placeholderChar: '_' 111 }); 112 return; 113 } 114 115 if (hasInputmask()) { 116 $contact.inputmask('mask', { 117 mask: phoneMask(), 118 showMaskOnHover: false, 119 showMaskOnFocus: true, 120 clearIncomplete: false 121 }); 122 return; 123 } 124 125 $contact.on('input.consultPhoneMask', function () { 126 var formatted = formatPhoneFallback(this.value); 127 if (this.value !== formatted) { 128 this.value = formatted; 129 } 130 }); 131 } 132 133 function setChannel(channel) { 134 var prev = $channelInput.val(); 135 destroyMask(); 136 $channelInput.val(channel); 137 $form.find('.consult-widget-form__tab').each(function () { 138 var active = $(this).data('channel') === channel; 139 $(this).toggleClass('is-active', active).attr('aria-selected', active ? 'true' : 'false'); 140 }); 141 $contact.attr({ 142 type: channel === 'mail' ? 'email' : 'tel', 143 autocomplete: channel === 'mail' ? 'email' : 'tel', 144 inputmode: channel === 'mail' ? 'email' : 'tel', 145 placeholder: PLACEHOLDERS[channel] || PLACEHOLDERS.mail 146 }); 147 if (prev === 'mail' || channel === 'mail') { 148 $contact.val(''); 149 } 150 applyMask(channel); 151 clearError('contact'); 152 } 153 154 function openPopup() { 155 $overlay.addClass('is-open').prop('hidden', false); 156 $popup.addClass('is-open').prop('hidden', false); 157 $widget.addClass('is-hidden'); 158 $('body').addClass('consult-widget-lock'); 159 setTimeout(function () { 160 $contact.trigger('focus'); 161 }, 50); 162 } 163 164 function closePopup() { 165 $overlay.removeClass('is-open').prop('hidden', true); 166 $popup.removeClass('is-open is-success').prop('hidden', true); 167 $widget.removeClass('is-hidden'); 168 $('body').removeClass('consult-widget-lock'); 169 $submit.prop('disabled', false); 170 } 171 172 function clearError(name) { 173 $form.find('[data-field="' + name + '"]').removeClass('is-error'); 174 $form.find('[data-error="' + name + '"]').text(''); 175 } 176 177 function showError(name, message) { 178 var $field = $form.find('[data-field="' + name + '"]'); 179 $field.addClass('is-error'); 180 $field.find('[data-error="' + name + '"]').text(message); 181 } 182 183 function digitsPhone(value) { 184 var digits = String(value || '').replace(/\D+/g, ''); 185 if (digits.charAt(0) === '8') { 186 digits = '7' + digits.slice(1); 187 } 188 if (digits.charAt(0) !== '7') { 189 digits = '7' + digits; 190 } 191 return digits; 192 } 193 194 function isValidEmail(value) { 195 return /^[^\s@]+@[^\s@]+\.[a-zA-Z]{2,}$/.test(String(value || '').trim()); 196 } 197 198 function isValidPhone(value) { 199 return digitsPhone(value).length === 11; 200 } 201 202 function fileExt(name) { 203 var parts = String(name || '').toLowerCase().split('.'); 204 return parts.length > 1 ? parts.pop() : ''; 205 } 206 207 function shortFileName(name) { 208 var full = String(name || ''); 209 if (full.length <= FILE_NAME_MAX) { 210 return full; 211 } 212 var ext = ''; 213 var dot = full.lastIndexOf('.'); 214 if (dot > 0 && full.length - dot <= 8) { 215 ext = full.slice(dot); 216 full = full.slice(0, dot); 217 } 218 var keep = Math.max(10, FILE_NAME_MAX - ext.length - 1); 219 return full.slice(0, keep) + 'â¦' + ext; 220 } 221 222 function unwrapFileInput() { 223 if (!$fileInput || !$fileInput.length) { 224 return; 225 } 226 var $uploader = $fileInput.closest('.uploader'); 227 if ($uploader.length) { 228 $uploader.after($fileInput); 229 $uploader.remove(); 230 } 231 $fileInput.attr({ hidden: true, tabindex: -1, 'aria-hidden': 'true' }); 232 } 233 234 function renderFiles() { 235 if (!selectedFiles.length) { 236 $fileList.prop('hidden', true).empty(); 237 $fileStatus.prop('hidden', false).text('Файл не вÑбÑан'); 238 return; 239 } 240 $fileStatus.prop('hidden', true); 241 $fileList.prop('hidden', false).empty();
242 selectedFiles.forEach(function (file, index) { 243 var $item = $('<div class="consult-widget-form__file-item"/>'); 244 $item.append( 245 $('<span/>').text(shortFileName(file.name)).attr('title', file.name) 246 ); 247 $item.append( 248 $('<button type="button" class="consult-widget-form__file-remove" aria-label="УдалиÑÑ Ñайл" title="УдалиÑÑ">×</button>') 249 .on('click', function () { 250 selectedFiles.splice(index, 1); 251 renderFiles(); 252 }) 253 ); 254 $fileList.append($item); 255 }); 256 } 257 258 function addFiles(fileList) { 259 var files = Array.prototype.slice.call(fileList || []); 260 files.forEach(function (file) { 261 if (selectedFiles.length >= MAX_FILES) { 262 return; 263 } 264 var ext = fileExt(file.name); 265 if (ALLOWED_EXT.indexOf(ext) === -1) { 266 showError('contact', ''); 267 alert('ÐопÑÑÑимÑе ÑоÑмаÑÑ: ' + ALLOWED_EXT.join(', ')); 268 return; 269 } 270 if (file.size > MAX_SIZE) { 271 alert('Файл «' + file.name + '» болÑÑе 10 ÐÐ'); 272 return; 273 } 274 selectedFiles.push(file); 275 }); 276 renderFiles(); 277 $fileInput.val(''); 278 } 279 280 function validate() { 281 var ok = true; 282 var channel = $channelInput.val(); 283 var value = $.trim($contact.val()); 284 clearError('contact'); 285 clearError('agree'); 286 287 if (!value) { 288 showError('contact', channel === 'mail' ? 'УкажиÑе e-mail' : 'УкажиÑе ÑелеÑон'); 289 ok = false; 290 } else if (channel === 'mail' && !isValidEmail(value)) { 291 showError('contact', 'УкажиÑе коÑÑекÑнÑй e-mail'); 292 ok = false; 293 } else if ((channel === 'phone' || channel === 'max') && !isValidPhone(value)) { 294 showError('contact', 'УкажиÑе коÑÑекÑнÑй ÑелеÑон'); 295 ok = false; 296 } 297 298 if (!$form.find('input[name="agree"]').prop('checked')) { 299 showError('agree', 'ÐодÑвеÑдиÑе ÑоглаÑие'); 300 ok = false; 301 } 302 303 return ok; 304 } 305 306 function submitForm(e) { 307 e.preventDefault(); 308 if (!validate()) { 309 return; 310 } 311 312 var data = new FormData($form.get(0)); 313 data.delete('files[]'); 314 selectedFiles.forEach(function (file) { 315 data.append('files[]', file, file.name); 316 }); 317 318 $submit.prop('disabled', true); 319 320 $.ajax({ 321 url: $form.attr('action'), 322 method: 'POST', 323 data: data, 324 processData: false, 325 contentType: false, 326 dataType: 'json' 327 }).done(function (res) { 328 if (res && res.success) { 329 reachGoal('widget_form_send'); 330 $popup.addClass('is-success'); 331 $form.trigger('reset'); 332 selectedFiles = []; 333 renderFiles(); 334 setChannel('mail'); 335 return; 336 } 337 if (res && res.errors) { 338 if (res.errors.contact) { 339 showError('contact', res.errors.contact); 340 } 341 if (res.errors.agree) { 342 showError('agree', res.errors.agree); 343 } 344 if (res.errors.form) { 345 alert(res.errors.form); 346 } 347 } else { 348 alert('Ðе ÑдалоÑÑ Ð¾ÑпÑавиÑÑ Ð·Ð°ÑвкÑ. ÐопÑобÑйÑе еÑÑ Ñаз.'); 349 } 350 $submit.prop('disabled', false); 351 }).fail(function () { 352 alert('Ðе ÑдалоÑÑ Ð¾ÑпÑавиÑÑ Ð·Ð°ÑвкÑ. ÐопÑобÑйÑе еÑÑ Ñаз.'); 353 $submit.prop('disabled', false); 354 }); 355 } 356 357 $(function () { 358 $widget = $('#consult-widget'); 359 if (!$widget.length) { 360 return; 361 } 362
363 $overlay = $('#consult-widget-overlay'); 364 $popup = $('#consult-widget-popup'); 365 $form = $('#consult-widget-form'); 366 $contact = $('#consult-widget-contact'); 367 $channelInput = $form.find('input[name="channel"]'); 368 $fileInput = $('#consult-widget-file-input'); 369 $fileStatus = $('#consult-widget-file-status'); 370 $fileList = $('#consult-widget-file-list'); 371 $submit = $form.find('.consult-widget-form__submit'); 372 unwrapFileInput(); 373 setTimeout(unwrapFileInput, 50); 374 setTimeout(unwrapFileInput, 400); 375 376 $widget.on('click', function () { 377 reachGoal('widget_click'); 378 openPopup(); 379 }); 380 381 $('#consult-widget-close').on('click', closePopup); 382 $overlay.on('click', closePopup); 383 384 $(document).on('keydown.consultWidget', function (e) { 385 if (e.key === 'Escape' && $popup.hasClass('is-open')) { 386 closePopup(); 387 } 388 }); 389 390 $form.on('click', '.consult-widget-form__tab', function () { 391 setChannel($(this).data('channel')); 392 }); 393 394 $contact.on('input', function () { 395 clearError('contact'); 396 }); 397 398 $form.find('input[name="agree"]').on('change', function () { 399 clearError('agree'); 400 }); 401 402 $('#consult-widget-attach').on('click', function () { 403 $fileInput.trigger('click'); 404 }); 405 406 $fileInput.on('change', function () { 407 addFiles(this.files); 408 }); 409 410 $form.on('submit', submitForm); 411 setChannel('mail'); 412 }); 413 } 414 415 function boot() { 416 if (window.jQuery) { 417 start(window.jQuery); 418 return; 419 } 420 if (boot.tries > 40) { 421 return; 422 } 423 boot.tries = (boot.tries || 0) + 1; 424 setTimeout(boot, 50); 425 } 426 427 if (document.readyState === 'loading') { 428 document.addEventListener('DOMContentLoaded', boot); 429 } else { 430 boot(); 431 } 432})();
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.