$(document).ready(function(){ $(document).on('submit', '.js-form', async function(e){ e.preventDefault(); let $form = $(this); let $btn = $form.find('[type="submit"]'); // it is necessary that if the first condition didn't pass, invalid files also showed const isValidFile = checkCustomFiles($form); if ($form[0].checkValidity() === false || isValidFile === false) { e.stopPropagation(); } else { $form.find('[data-code="SOURCE"]').val(window.location.href); startBtnLoad($btn); // just convert serialized array to obj let dataArr = $form.serializeArray().concat(await loadFiles($form)); let data = convertFormArrToObj(dataArr); BX.ajax.runComponentAction('ranx:form.landing', 'submit', {mode: 'class', data: {post: data}}).then(function(res){ $form.addClass('form-success'); $form.removeClass('was-validated') $form.trigger('reset'); initForms(); endBtnLoad($btn); }, function(res){ $form.find('input[name="captcha_word"]')[0].setCustomValidity(''); $form.find('.form-captcha').siblings('.invalid-feedback').hide(); if (res.errors[0].message === 'captcha') { $form.find('input[name="captcha_word"]')[0].setCustomValidity('Wrong symbols'); $form.find('.form-captcha').siblings('.invalid-feedback').show(); reloadCaptcha($form); } else { $form.addClass('form-error'); } endBtnLoad($btn); }); } $form.addClass('was-validated'); }); $(document).on('change keyup paste', '.js-form input[name="captcha_word"]', function(e){ if ($(this).val()) { $(this)[0].setCustomValidity(''); $(this).closest('.form-captcha').siblings('.invalid-feedback').hide(); } else { $(this)[0].setCustomValidity('Wrong symbols'); $(this).closest('.form-captcha').siblings('.invalid-feedback').show(); } }); // return back to the form and reload captcha $(document).on('click', '.js-form-back', function(e){ e.preventDefault(); let $form = $(this).closest('form') $form.removeClass('form-success form-error'); reloadCaptcha($form); }); // reload captcha on clicking on captcha img $(document).on('click', 'form .form-captcha img', function(e){ e.preventDefault(); let $form = $(this).closest('form') reloadCaptcha($form); }); $(document).on('click', '.js-form-modal', function(e){ e.preventDefault(); let $this = $(this); let formCode = $(this).data('form-code'); let subject = $(this).data('subject') || ''; startBtnLoad($this); BX.ajax.runComponentAction('ranx:form.landing', 'getModal', {mode: 'class', data: {post: { formCode: formCode, subject: subject }}}).then(function(res){ $('#formModal .modal-title').html(res.data.title); $('#formModal .modal-body').html(res.data.body); $('#formModal').modal(); endBtnLoad($this); initMasks(); initForms(); }); }); $(document).on('click', '.js-form-agreement', function(e){ e.preventDefault(); let $this = $(this); let formCode = $this.data('form-code'); BX.ajax.runComponentAction('ranx:form.landing', 'getAgreement', {mode: 'class', data: {post: { formCode: formCode }}}).then(function(res){ $('#agreementModal .modal-title').html(res.data.title); $('#agreementModal .modal-body').html(res.data.body); $('#agreementModal').modal(); }); }); $(document).on('click', '.js-form-politics', function(e){ e.preventDefault(); BX.ajax.runComponentAction('ranx:form.landing', 'getPolitics', {mode: 'class'}).then(function(res){ $('#agreementModal .modal-title').html(res.data.title); $('#agreementModal .modal-body').html(res.data.body); $('#agreementModal').modal(); }); }); $(document).on('change keyup paste', 'form input[type="text"].form-control, ' + 'form input[type="email"].form-control, form input[type="tel"].form-control, form textarea.form-control', function(e){ if ($(this).val()) { $(this).removeClass('empty'); } else { $(this).addClass('empty'); } }); // custom file input events and function $(document).on('change', '.form-custom-file-wrapper .form-custom-file-input', function (e) { const $fileWrapper = $(this).closest('.form-custom-file-wrapper'); const fileName = $(this).val().split('\\').pop(); hideInvalidFeedback($fileWrapper); if (!fileName) { resetCustomFile.call($fileWrapper); return; } $(this).siblings('.form-custom-file-name').text(fileName); $fileWrapper.addClass('file-selected'); }); $(document).on('click', '.form-custom-file-wrapper .form-custom-file-close', function (e) { const $fileWrapper = $(this).closest('.form-custom-file-wrapper').each(resetCustomFile); }) $(document).on('reset', '.js-form', function() { $(this).find('.form-custom-file-wrapper').each(resetCustomFile); }); function resetCustomFile() { const $fileWrapper = $(this); $fileWrapper.removeClass('file-selected'); $fileWrapper.find('.form-control-file').val(''); hideInvalidFeedback($fileWrapper); } function hideInvalidFeedback($fileWrapper) { $fileWrapper.siblings('.invalid-feedback').removeClass('active'); $fileWrapper.removeClass('invalid'); } function checkExtensions(file, accept) { const exts = accept.split(', '); const fileExt = '.' + file.name.split('.').pop(); return exts.includes(fileExt); } function checkCustomFiles($form) { let isValid = true; $form.find('.form-custom-file-input').each(function () { const $fileWrapper = $(this).closest('.form-custom-file-wrapper'); const file = $(this).prop('files')[0]; const isRequired = !!$(this).prop('required'); const maxSize = parseInt($(this).attr('size')); const accept = $(this).prop('accept'); if (!file) { if (!isRequired) { return; } $fileWrapper.siblings('.invalid-feedback.invalid-required').addClass('active'); } else if (maxSize && file.size > maxSize) { $fileWrapper.siblings('.invalid-feedback.invalid-maxsize').addClass('active'); } else if (accept && !checkExtensions(file, accept)) { $fileWrapper.siblings('.invalid-feedback.invalid-ext').addClass('active'); } else { return; } isValid = false; $fileWrapper.addClass('invalid'); }); return isValid; } initForms(); }); function reloadCaptcha($form) { BX.ajax.runComponentAction('ranx:form.landing', 'reloadCaptcha', {mode: 'class'}).then(function(res){ $form.find('input[name="captcha_sid"]').val(res.data); $form.find('.form-captcha img').attr('src', '/bitrix/tools/captcha.php?captcha_sid=' + res.data); }); } function initForms() { $('form input[type="text"].form-control, form input[type="email"].form-control, ' + 'form input[type="tel"].form-control, form textarea.form-control').each(function(e){ if ($(this).val()) { $(this).removeClass('empty'); } else { $(this).addClass('empty'); } }); } async function loadFiles($form) { let files = []; let promises = []; $form.find('.form-control-file').each(function () { const file = $(this).prop('files')[0]; const name = $(this).attr('name'); promises.push(new Promise((resolve, reject) => { const reader = new FileReader(); reader.readAsDataURL(file); reader.onload = () => resolve({ name: name, value: {fileName: file.name, type: 'file', data: reader.result }}); reader.onerror = (error) => reject(error); })); }); // if the browser doesn't support allSettled if(!Promise.allSettled) { Promise.allSettled = function(promises) { return Promise.all(promises.map(p => Promise.resolve(p).then(value => ({ status: 'fulfilled', value: value }), error => ({ status: 'rejected', reason: error })))); }; } let results = await Promise.allSettled(promises); $.each(results, function () { if (this.status === 'fulfilled') { files.push(this.value); } }); return files; }