/* ==================================================================== ОБЕРТКА ДЛЯ ОЖИДАНИЯ JQUERY ==================================================================== */ (function waitForJQuery() { if (typeof jQuery === 'undefined') { setTimeout(waitForJQuery, 10); } else { (function($) { if (typeof aveabspath === 'undefined') { window.aveabspath = '/'; } function initCommentTimers() { $('.timer-count:not(.timer-running)').each(function() { var $timer = $(this); var timeLeft = parseInt($timer.attr('data-left')); // Если время не определено или уже вышло — помечаем как запущенный и пропускаем if (isNaN(timeLeft) || timeLeft <= 0) { $timer.addClass('timer-running'); return; } $timer.addClass('timer-running'); var cid = $timer.attr('id').replace('timer_', ''); var countdown = setInterval(function() { timeLeft--; if (timeLeft <= 0) { clearInterval(countdown); // --- Проверка режима редактирования --- var isEditing = $('#comment_wrapper_' + cid).find('.edit-form-container').length > 0; if (!isEditing) { // Находим кнопки управления var $controls = $('#controls_' + cid); if ($controls.length) { $controls.fadeOut(300, function() { $(this).remove(); }); } // Обновляем статус визуально $('#timer_container_' + cid).html('' + COMMENT_JS_TIMER_OFF + ''); } else { // Если открыта форма редактирования, просто меняем текст, не удаляя кнопки $('#timer_container_' + cid).html('' + COMMENT_JS_TIMER_OFF_A + ''); } return; } // Форматируем вывод 00:00 var minutes = Math.floor(timeLeft / 60); var seconds = timeLeft % 60; $timer.text(minutes + ':' + (seconds < 10 ? '0' : '') + seconds); $timer.attr('data-left', timeLeft); }, 1000); $timer.data('interval-id', countdown); }); } /* Limit Plugin */ $.fn.extend({ limit: function(limit, element) { return this.each(function() { var self = $(this); function substring() { var val = self.val(); if (val.length > limit) self.val(val.substring(0, limit)); if (typeof element !== 'undefined') { var remaining = limit - self.val().length; $(element).html(remaining < 0 ? '0' : remaining); } } self.on('focus keyup paste', substring); substring(); }); } }); function getCaptha() { var now = new Date(); $('#captcha img').attr('src', aveabspath + 'inc/captcha.php?cd=' + now.getTime()); } // ВАЛИДАЦИЯ ПОЛЕЙ // Функция для проверки файла (расширение и размер) function checkFileConsistency(file, $errorDisplay) { if (!file) return true; // Получаем настройки из шаблона var allowedExts = (typeof ALLOWED_EXTENSIONS !== 'undefined') ? ALLOWED_EXTENSIONS.toLowerCase().split(',') : ['jpg', 'jpeg', 'png', 'gif, webp']; var maxSizeKb = (typeof MAX_FILE_SIZE_KB !== 'undefined') ? parseInt(MAX_FILE_SIZE_KB) : 2048; var fileName = file.name.toLowerCase(); var fileExt = fileName.split('.').pop(); var fileSizeKb = file.size / 1024; // Проверка расширения if ($.inArray(fileExt, allowedExts) === -1) { $errorDisplay.text(COMMENT_JS_FILE_TYPE + ' .' + fileExt + ' ' + COMMENT_JS_FILE_TYPE_A).removeClass('d-none'); return false; } // Проверка размера if (fileSizeKb > maxSizeKb) { $errorDisplay.text(COMMENT_JS_FILE_SIZE + ' (' + Math.round(fileSizeKb) + COMMENT_JS_FILE_SIZE_KB + '). ' + COMMENT_JS_FILE_SIZE_MAX + ' ' + maxSizeKb + COMMENT_JS_FILE_SIZE_KB).removeClass('d-none'); return false; } $errorDisplay.addClass('d-none').text(''); return true; } function validate(form) { var isValid = true; // Вспомогательная функция для подсветки function setInvalid($el, show, msg) { if (show) { $el.addClass('is-invalid'); if ($el.next('.invalid-feedback').length === 0) { $el.after('
' + msg + '
'); } isValid = false; } else { $el.removeClass('is-invalid'); $el.next('.invalid-feedback').remove(); } } // Проверка Имени setInvalid($(form.comment_author_name), !form.comment_author_name.value.trim(), COMMENT_JS_CHECK_NAME); // Проверка Email setInvalid($(form.comment_author_email), !form.comment_author_email.value.trim(), COMMENT_JS_CHECK_EMAIL); // Проверка Доп. поля №1 (если оно обязательное) if (typeof REQ_F1 !== 'undefined' && REQ_F1 == '1') { var f1 = $('#in_author_website'); setInvalid(f1, !f1.val().trim(), COMMENT_JS_FILL + " " + NAME_F1); } // Проверка Доп. поля №2 (если оно обязательное) if (typeof REQ_F2 !== 'undefined' && REQ_F2 == '1') { var f2 = $('#in_author_city'); setInvalid(f2, !f2.val().trim(), COMMENT_JS_FILL + " " + NAME_F2); } // Проверка Текста setInvalid($(form.comment_text), !form.comment_text.value.trim(), COMMENT_JS_ADD_COMMENT_TEXT); // Проверка файлов в основной форме (Мультизагрузка) var $fileInput = $(form).find('#comment_image'); if ($fileInput.length && $fileInput[0].files.length > 0) { var files = $fileInput[0].files; for (var i = 0; i < files.length; i++) { if (!checkFileConsistency(files[i], $('#file_error'))) { $fileInput.addClass('is-invalid'); isValid = false; break; } } } if (!isValid) { // Скроллим к первой ошибке $('html, body').animate({ scrollTop: $('.is-invalid:first').offset().top - 130 }, 300); } return isValid; } /* --- ДЕЙСТВИЯ (DELETE, LOCK, OPEN/CLOSE, VOTE) --- */ function cAction(obj, action) { var $btn = $(obj); var cid = $btn.data('id'); if (!cid && action !== 'open' && action !== 'close') return; $.get(aveabspath + 'index.php', { module: 'comment', action: action, docid: typeof DOC_ID !== 'undefined' ? DOC_ID : '', Id: cid ? cid : '' }, function() { if (action === 'close') { $btn.attr('id', 'mod_comment_open') .removeClass('btn-outline-danger').addClass('btn-outline-success') .html(' ' + COMMENT_SITE_OPEN); $('#mod_comment_new').fadeOut(300); } else if (action === 'open') { $btn.attr('id', 'mod_comment_close') .removeClass('btn-outline-success').addClass('btn-outline-danger') .html(' ' + COMMENT_SITE_CLOSE); $('#mod_comment_new').fadeIn(300); } if (action === 'delete') { var $commentBlock = $btn.closest('.mod_comment_comment'); $commentBlock.fadeOut(300, function() { $(this).remove(); }); } // показать / скрыть комментарий // показать / скрыть комментарий if (action === 'unlock' || action === 'lock') { var $icon = $btn.find('i'); var $card = $btn.closest('.mod_comment_comment'); if (action === 'lock') { // --- Статус 0: СКРЫТО --- $icon.attr('class', 'bi bi-eye-slash'); $btn.removeClass('text-success text-muted').addClass('text-danger').attr('title', COMMENT_ICON_SHOW); $card.addClass('opacity-75 border-warning'); // Ищем плашку. Если её нет — создаем один раз. var $alert = $card.find('.alert-warning'); if ($alert.length === 0) { var alertHtml = ''; $card.find('.flex-grow-1').prepend(alertHtml); $alert = $card.find('.alert-warning'); } $alert.stop(true, true).fadeIn(300); } else { // --- Статус 1: ВИДИМО --- $icon.attr('class', 'bi bi-eye'); $btn.removeClass('text-danger text-muted').addClass('text-success').attr('title', COMMENT_ICON_HIDE); $card.removeClass('opacity-75 border-warning'); // Надежное скрытие: используем callback, чтобы после анимации точно убрать элемент $card.find('.alert-warning').stop(true, true).fadeOut(300, function() { $(this).remove(); // Удаляем плашку из кода совсем, чтобы при следующем "скрыть" она создалась чисто }); } } }); } /* --- ИНИЦИАЛИЗАЦИЯ --- */ $(document).ready(function() { initCommentTimers(); var $doc = $(document); // Убираем красную рамку, когда пользователь начинает исправлять поле $doc.on('input change', '.form-control', function() { $(this).removeClass('is-invalid'); $(this).next('.invalid-feedback').fadeOut(200, function() { $(this).remove(); }); }); // Инициализация тултипов для всех элементов с data-bs-toggle="tooltip" var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]')) var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) { return new bootstrap.Tooltip(tooltipTriggerEl) }) // Счетчик: Количество оставшихся символов 1000 для формы создания комментария // Используем переменную MAX_CHARS, которая приходит из настроек модуля $('#in_message').limit(MAX_CHARS, '#charsLeft_new'); $doc.on('change', '#comment_image', function() { var input = this; var $errorBox = $('#file_error'); var $previewWrapper = $('#image_preview_wrapper'); $previewWrapper.empty().addClass('d-none'); $errorBox.addClass('d-none'); $(input).removeClass('is-invalid'); if (input.files && input.files.length > 0) { var files = Array.from(input.files); $previewWrapper.removeClass('d-none').addClass('d-flex flex-wrap gap-2'); files.forEach(function(file) { if (checkFileConsistency(file, $errorBox)) { var reader = new FileReader(); reader.onload = function(e) { var imgHtml = `
`; $previewWrapper.append(imgHtml); } reader.readAsDataURL(file); } else { $(input).val('').addClass('is-invalid'); $previewWrapper.addClass('d-none'); } }); } }); // обработчик, доработанный под мультизагрузку $doc.on('click', '#remove_image_btn', function() { $('#comment_image').val(''); // Очищаем выбор файлов $('#image_preview_wrapper').addClass('d-none').empty(); // Скрываем и полностью очищаем блок превью }); // удаление картинок по одной (крестиком на самой картинке) $doc.on('click', '.remove-new-img', function() { $(this).closest('.preview-item').remove(); // Удаляем только этот контейнер с картинкой // Если после удаления картинок внутри не осталось — скрываем обертку и чистим инпут if ($('#image_preview_wrapper').children().length === 0) { $('#image_preview_wrapper').addClass('d-none'); $('#comment_image').val(''); } }); // --- ВЫБОР РЕЙТИНГА В ФОРМЕ --- $doc.on('mouseenter', '.star-choice', function() { var val = $(this).data('value'); $(this).parent().find('.star-choice').each(function() { if ($(this).data('value') <= val) { $(this).removeClass('bi-star').addClass('bi-star-fill'); } else { $(this).removeClass('bi-star-fill').addClass('bi-star'); } }); }); $doc.on('mouseleave', '.rating-edit-block, #rating_wrapper', function() { var $block = $(this); var currentRating; if ($block.attr('id') === 'rating_wrapper') { currentRating = parseInt($('#comment_user_rating').val()) || 0; } else { var cid = $block.find('input[type="hidden"]').attr('id').replace('rating_input_', ''); currentRating = parseInt($('#rating_input_' + cid).val()) || 0; } $block.find('.star-choice').each(function() { if ($(this).data('value') <= currentRating) { $(this).removeClass('bi-star').addClass('bi-star-fill'); } else { $(this).removeClass('bi-star-fill').addClass('bi-star'); } }); }); $doc.on('click', '.star-choice', function() { var val = $(this).data('value'); var ratingInput = $(this).closest('.rating-edit-block').find('input[type="hidden"]'); if (ratingInput.length) { ratingInput.val(val); } else { $('#comment_user_rating').val(val); } $(this).prevAll().addBack().removeClass('bi-star').addClass('bi-star-fill'); $(this).nextAll().removeClass('bi-star-fill').addClass('bi-star'); }); $doc.on('click', '#buttonReset', function() { $('#comment_user_rating').val(0); $('#user_rating_stars .star-choice').removeClass('bi-star-fill').addClass('bi-star'); $('#rating_wrapper').show(); // Показываем блок рейтинга обратно $('#image_preview_wrapper').addClass('d-none'); $('#charsLeft_new').text(MAX_CHARS); $('.form-control').removeClass('is-invalid'); $('.invalid-feedback').remove(); $('#parent_id').val(''); // Очищаем ID родителя, чтобы комментарий снова стал корневым }); $doc.on('click', '#reset_stars', function(e) { e.preventDefault(); $('#comment_user_rating').val(0); $('#user_rating_stars .star-choice').removeClass('bi-star-fill').addClass('bi-star'); }); $doc.on('click', '.reset-edit-stars', function(e) { e.preventDefault(); var cid = $(this).data('id'); $('#rating_input_' + cid).val(0); $('#user_rating_stars_' + cid + ' .star-choice').removeClass('bi-star-fill').addClass('bi-star'); }); // --- ГОЛОСОВАНИЕ (РЕЙТИНГ УЖЕ ОПУБЛИКОВАННЫХ) --- $doc.on('mouseenter', '.star-item', function() { var $parent = $(this).parent(); if ($parent.hasClass('comment-like')) { $(this).css('transform', 'scale(1.2)'); } else { $(this).prevAll().addBack().removeClass('bi-star').addClass('bi-star-fill'); $(this).nextAll().removeClass('bi-star-fill').addClass('bi-star'); } }); $doc.on('mouseleave', '.star-item', function() { var $parent = $(this).parent(); if ($parent.hasClass('comment-like')) { $(this).css('transform', 'scale(1)'); } }); $doc.on('click', '.star-item', function() { var $container = $(this).closest('.comment-rating-container'); var commentId = $container.data('id'); var voteValue = $(this).data('value'); $.ajax({ url: 'index.php?module=comment&action=vote&ajax=1', type: 'POST', data: { comment_id: commentId, vote: voteValue, ajax: 1 }, success: function(response) { var res = response.toString().trim(); if (res.indexOf('success') !== -1) { $container.html('' + COMMENT_JS_THX + ''); setTimeout(function(){ location.reload(); }, 1000); } else if (res.indexOf('already_voted') !== -1) { alert(COMMENT_JS_VOTE_A); } else if (res.indexOf('own_comment') !== -1) { alert(COMMENT_JS_VOTE_B); } else if (res.indexOf('forbidden_anon') !== -1) { alert(COMMENT_JS_VOTE_C); } else { alert(COMMENT_JS_VOTE_ERR); } }, error: function(xhr) {alert(COMMENT_JS_VOTE_ERR_A + ' ' + xhr.status);} }); }); $doc.on('click', '#mod_comment_close', function(e) { e.preventDefault(); cAction(this, 'close'); }); $doc.on('click', '#mod_comment_open', function(e) { e.preventDefault(); cAction(this, 'open'); }); // КНОПКА ОТВЕТА $doc.off('click', '.mod_comment_answer').on('click', '.mod_comment_answer', function(e) { e.preventDefault(); var cid = $(this).data('id'); var $form = $('#mod_comment_new'); $form.insertAfter('#comment_' + cid).show(); $('#parent_id').val(cid); // --- СКРЫТИЕ РЕЙТИНГА ДЛЯ ОТВЕТОВ --- if (typeof SHOW_USER_RATING_REPLIES !== 'undefined' && SHOW_USER_RATING_REPLIES == '0') { $('#rating_wrapper').hide(); // Скрываем весь блок рейтинга $('#comment_user_rating').val(0); // Сбрасываем значение $('#user_rating_stars .star-choice').removeClass('bi-star-fill').addClass('bi-star'); } else { $('#rating_wrapper').show(); } // --- КОНЕЦ --- $('html, body').animate({ scrollTop: $form.offset().top - 150 }, 500); $('#in_message').focus(); }); // Удаление $doc.off('click', '.mod_comment_delete').on('click', '.mod_comment_delete', function(e) { e.preventDefault(); if (confirm(COMMENT_JS_DELDEL_CONFIRM)) cAction(this, 'delete'); }); // Универсальный обработчик для переключателя видимости // Оставляем все селекторы для надежности $doc.off('click', '.mod_comment_toggle, .mod_comment_lock, .mod_comment_unlock') .on('click', '.mod_comment_toggle, .mod_comment_lock, .mod_comment_unlock', function(e) { e.preventDefault(); var $btn = $(this); var $icon = $btn.find('i'); // Теперь проверяем перечеркнутый глаз (скрыто) или закрытый замок (на случай если остался в кэше) // Если глаз перечеркнут ИЛИ замок закрыт — значит в базе 0, шлем 'unlock' var isHidden = $icon.hasClass('bi-eye-slash') || $icon.hasClass('bi-lock-fill'); var actionToSend = isHidden ? 'unlock' : 'lock'; cAction(this, actionToSend); }); // НАЧАЛО $doc.off('click', '.mod_comment_edit') РЕДАКТИРОВАНИЕ КОММЕНТАРИЯ $doc.off('click', '.mod_comment_edit').on('click', '.mod_comment_edit', function(e) { e.preventDefault(); var cid = $(this).data('id'); var $wrapper = $('#comment_wrapper_' + cid); if ($wrapper.length === 0) { console.error("Обертка #comment_wrapper_" + cid + " не найдена!"); return; } var $textBlock = $wrapper.find('.mod_comment_text').first(); // Пытаемся найти блок с картинками var $attachedImagesBlock = $wrapper.find('.mod_comment_attached_image'); if ($attachedImagesBlock.length === 0) { $attachedImagesBlock = $wrapper.find('.comment-files, .attached-images'); } if ($wrapper.find('.edit-form-container').length > 0) return; var isMyOwn = $wrapper.attr('data-is-own') == '1'; var currentRating = parseInt($wrapper.attr('data-user-rating')) || 0; $('.edit-form-container').remove(); $('.mod_comment_text').show(); $('.mod_comment_attached_image, .comment-files').show(); var cleanText = $textBlock.html().replace(//mg, "\n").trim(); // --- СБОР ТЕКУЩИХ ВЛОЖЕНИЙ --- var existingImagesHtml = ''; var $imageContainer = $('#image_container_' + cid); // Ищем именно "карточки" из шаблона (класс .comment-image-item) var $foundItems = $imageContainer.find('.comment-image-item'); if ($foundItems.length > 0) { existingImagesHtml = '
'; $foundItems.each(function(index) { var $item = $(this); var $link = $item.find('a'); var fileUrl = $link.attr('href'); if (!fileUrl) return; var fileName = fileUrl.split('/').pop(); var fileExt = fileName.split('.').pop().toLowerCase(); var isImg = ['jpg', 'jpeg', 'png', 'gif', 'webp'].includes(fileExt); // Используем стиль превью var previewContent = isImg ? `` : `
${fileExt}
`; existingImagesHtml += `
${previewContent}
`; }); existingImagesHtml += '
'; } // --- РЕЙТИНГ --- var starsEditBlock = ''; var parentIdVal = parseInt($wrapper.attr('data-parent')) || 0; var isReply = parentIdVal > 0; var ratingForbiddenForReply = (isReply && typeof SHOW_USER_RATING_REPLIES !== 'undefined' && SHOW_USER_RATING_REPLIES == '0'); if (typeof SHOW_USER_RATING !== 'undefined' && SHOW_USER_RATING == '1' && isMyOwn && !ratingForbiddenForReply) { if (typeof UGROUP !== 'undefined' && (UGROUP != '2' || RATING_ANON_SET == '1')) { var starsHtml = ''; for(var i=1; i<=5; i++) { var starClass = (i <= currentRating) ? 'bi-star-fill' : 'bi-star'; starsHtml += ``; } starsEditBlock = `
`; } } // --- СБОРКА ФОРМЫ --- var editHtml = `
${starsEditBlock}

${COMMENT_JS_LOADED_FILES}

${existingImagesHtml}
${COMMENT_JS_EDIT_BUT_LEFT}
`; // Прячем текст комментария $textBlock.hide(); // Прячем ВЕСЬ контейнер с файлами $('#image_container_' + cid).attr('style', 'display: none !important;'); // Для надежности скрываем всё остальное $wrapper.find('.mod_comment_attached_images, .comment-files').hide(); $textBlock.after(editHtml); // --- НАКОПИТЕЛЬНОЕ ПРЕВЬЮ НОВЫХ ФАЙЛОВ --- var pendingFiles = []; // Массив для хранения всех выбранных файлов $wrapper.find('.edit-form-container').data('pendingFiles', pendingFiles); $('#new_file_' + cid).on('change', function() { var files = this.files; var $input = $(this); var $currentEditForm = $input.closest('.edit-form-container'); var $errorDisplay = $currentEditForm.find('.js-file-error'); var maxLimit = parseInt(typeof MAX_FILES_COUNT !== 'undefined' ? MAX_FILES_COUNT : 5); if (files) { $errorDisplay.text('').hide(); $.each(files, function(i, file) { var alreadyInPost = $currentEditForm.find('[id^="existing_wrapper_"]').length; var inPending = pendingFiles.filter(f => f !== null).length; if ((alreadyInPost + inPending) >= maxLimit) { $errorDisplay.text(' ' + COMMENT_JS_LIMIT_AB + ' ' + maxLimit + ' ' + COMMENT_JS_LIMIT_ABC).show(); return false; } // ПРОВЕРКА ЧЕРЕЗ ФУНКЦИЮ (она берет ALLOWED_EXTENSIONS) if (!checkFileConsistency(file, $errorDisplay)) return true; pendingFiles.push(file); var currentIndex = pendingFiles.length - 1; var fileExt = file.name.split('.').pop().toLowerCase(); var isImage = ['jpg', 'jpeg', 'png', 'gif', 'webp'].includes(fileExt); var reader = new FileReader(); reader.onload = function(e) { var $previewContainer = $('#new_files_preview_' + cid); if ($previewContainer.length === 0) { $input.after(`
`); $previewContainer = $('#new_files_preview_' + cid); } var content = isImage ? `` : `
${fileExt}
`; $previewContainer.append(`
${content}
`); }; if (isImage) reader.readAsDataURL(file); else reader.onload({target: {result: ''}}); }); } }); // Обработчик удаления НОВОГО файла из превью (до сохранения) $doc.off('click', '.remove-new-file').on('click', '.remove-new-file', function() { var $item = $(this).closest('.new-file-item'); var index = $item.data('index'); pendingFiles[index] = null; // Помечаем как удаленный $item.remove(); // Ищем через ближайший контейнер формы, чтобы точно попасть в нужный блок текста $(this).closest('.edit-form-container').find('.js-file-error').hide().text(''); }); // --- КОНЕЦ ВСТАВКИ --- // Добавил поддержку лимита символов if ($.fn.limit) { $('#ta_' + cid).limit(MAX_CHARS, '#charsLeft_' + cid); } $('#ta_' + cid).focus(); }); // КОНЕЦ $doc.off('click', '.mod_comment_edit') $doc.on('click', '.remove-existing-img', function() { var cid = $(this).data('id'); var imgPath = $(this).data('img-path'); var targetId = $(this).data('target'); // 1. Очищаем текст ошибки $('#file_error_' + cid).addClass('d-none').text(''); var $deleteInput = $('#delete_files_' + cid); var currentDeleteList = $deleteInput.val() ? $deleteInput.val().split(',') : []; if (currentDeleteList.indexOf(imgPath) === -1) { currentDeleteList.push(imgPath); $deleteInput.val(currentDeleteList.join(',')); } // 2. Скрываем и удвляем элемент, чтобы счетчик .length его больше не видел $('#' + targetId).fadeOut(300, function() { $(this).remove(); }); }); // Обработка выбора НОВОГО файла при редактировании $doc.on('change', 'input[id^="new_file_"]', function() { var cid = $(this).attr('id').replace('new_file_', ''); var input = this; // 1. Сначала находим блок var $errorBox = $('#file_error_' + cid); var $previewWrapper = $('#edit_preview_wrapper_' + cid); if (input.files && input.files.length > 0) { $previewWrapper.find('.preview-item-new').remove(); $previewWrapper.removeClass('d-none'); Array.from(input.files).forEach(function(file) { if (checkFileConsistency(file, $errorBox)) { // Если файл прошел проверку - только тогда можно спрятать ошибку $errorBox.addClass('d-none').text(''); var reader = new FileReader(); reader.onload = function(e) { var item = `
`; $previewWrapper.append(item); } reader.readAsDataURL(file); } }); } }); // Удаление НОВОГО выбранного файла в режиме редактирования $doc.on('click', '.remove-edit-new-img', function() { var cid = $(this).data('id'); $('#new_file_' + cid).val(''); $('#edit_preview_wrapper_' + cid).addClass('d-none'); }); // Обработка кнопки "Отмена" при редактировании $doc.on('click', '.cancelButton', function() { var $container = $(this).closest('.edit-form-container'); var $wrapper = $container.closest('[id^="comment_wrapper_"]'); var cid = $container.data('cid'); // Берем ID для обращения к контейнеру файлов // 1. Возвращаем текст $wrapper.find('.mod_comment_text').show(); // 2. Возвращаем оригинальный блок с картинками // СНАЧАЛА ЧИСТИМ ИНЛАЙН СТИЛЬ $('#image_container_' + cid).attr('style', ''); // Затем стандартный показ $wrapper.find('.mod_comment_attached_image, .mod_comment_attached_images, .comment-files, .attached-images').show(); // 3. Если мы скрывали изображения напрямую через $foundImgs.hide(), показываем их $wrapper.find('img').show(); // И ссылки $wrapper.find('a').show(); // 4. Удаляем форму редактирования $container.remove(); }); $doc.on('click', '.saveButton', function() { var $btn = $(this); var cid = $btn.data('id'); var $container = $btn.closest('.edit-form-container'); // Достаем накопительный массив файлов var pendingFiles = $container.data('pendingFiles') || []; var fd = new FormData(); fd.append('module', 'comment'); fd.append('action', 'edit'); fd.append('Id', cid); fd.append('text', $('#ta_' + cid).val()); var rInput = $('#rating_input_' + cid); if (rInput.length) fd.append('user_rating', rInput.val()); fd.append('delete_files', $('#delete_files_' + cid).val()); // --- берем файлы из массива --- pendingFiles.forEach(function(file) { if (file !== null) { // Проверяем, что файл не был удален крестиком fd.append('comment_image[]', file); } }); // ------------------------------------ $.ajax({ url: aveabspath + 'index.php?ajax=1', type: 'POST', data: fd, processData: false, contentType: false, xhr: function() { var xhr = new window.XMLHttpRequest(); xhr.upload.addEventListener("progress", function(evt) { if (evt.lengthComputable) { var pct = Math.round((evt.loaded / evt.total) * 100); $('#edit_progress_container_' + cid).removeClass('d-none'); $('#edit_progress_bar_' + cid).css('width', pct + '%'); } }, false); return xhr; }, beforeSend: function() { $btn.prop('disabled', true).text('...'); }, success: function() { location.reload(); } }); }); // Глобальный массив для файлов НОВОГО комментария var newCommentPendingFiles = []; // Обработка выбора файлов в основной форме // .off('change') чтобы не было дублей $doc.off('change', '#comment_image').on('change', '#comment_image', function() { var files = this.files; var $previewWrapper = $('#image_preview_wrapper'); var $errorDisplay = $('#file_error'); // 1. Лимит из настроек var maxLimit = parseInt(typeof MAX_FILES_COUNT !== 'undefined' ? MAX_FILES_COUNT : 5); if (files) { $errorDisplay.addClass('d-none').text(''); // Сбрасываем старые ошибки $.each(files, function(i, file) { // 2. Считаем, сколько сейчас РЕАЛЬНО файлов в очереди (не null) var currentInQueue = newCommentPendingFiles.filter(function(f) { return f !== null; }).length; // 3. ПРОВЕРКА ЛИМИТА: если уже достигли максимума if (currentInQueue >= maxLimit) { $errorDisplay.removeClass('d-none').text(COMMENT_JS_LIMIT_ABCD + maxLimit + ' ' + COMMENT_JS_LIMIT_ABCDE); return false; // break - полностью выходим из цикла $.each } // 4. Валидация (размер, расширение) if (typeof checkFileConsistency === 'function') { if (!checkFileConsistency(file, $errorDisplay)) { return true; // continue - этот файл плохой, идем к следующему } } // Если прошли все проверки — добавляем в очередь newCommentPendingFiles.push(file); var currentIndex = newCommentPendingFiles.length - 1; var reader = new FileReader(); reader.onload = function(e) { if ($previewWrapper.find(`[data-index="${currentIndex}"]`).length > 0) return; // Определяем, что вставить: картинку или заглушку с текстом расширения var fileExt = file.name.split('.').pop().toLowerCase(); var isImage = ['jpg', 'jpeg', 'png', 'gif', 'webp'].includes(fileExt); // Формируем контент: либо твой оригинальный img, либо блок с расширением var content = isImage ? `` : `
${fileExt}
`; $previewWrapper.removeClass('d-none'); $previewWrapper.append(`
${content}
`); }; reader.readAsDataURL(file); }); } // Очищаем инпут в любом случае, чтобы можно было выбрать те же файлы снова $(this).val(''); }); // Удаление выбранного файла из очереди в новой форме $doc.on('click', '.remove-new-comment-img', function() { var $item = $(this).closest('.new-comment-file-item'); var index = $item.data('index'); newCommentPendingFiles[index] = null; // Помечаем удаленным $('#file_error').addClass('d-none').text(''); $item.fadeOut(200, function() { $(this).remove(); if ($('#image_preview_wrapper').children().length === 0) { $('#image_preview_wrapper').addClass('d-none'); } }); }); // Очистка при нажатии кнопки "Сбросить" (reset) $doc.on('click', '#buttonReset', function() { newCommentPendingFiles = []; $('#image_preview_wrapper').empty().addClass('d-none'); // убрать текст ошибки $('#file_error').addClass('d-none').text(''); }); // Отправка новой формы (или ответа) $doc.on('submit', '#mod_comment_new form', function(e) { e.preventDefault(); if (!validate(this)) return false; var $form = $(this); var $btn = $form.find('[type="submit"]'); var originalBtnText = $btn.text(); var formData = new FormData(this); // 1. Удаляем стандартные значения, чтобы они не дублировались из инпута formData.delete('comment_image'); formData.delete('comment_image[]'); // 2. Добавляем файлы из нашего накопленного массива newCommentPendingFiles if (newCommentPendingFiles && newCommentPendingFiles.length > 0) { newCommentPendingFiles.forEach(function(file) { if (file !== null) { formData.append('comment_image[]', file); } }); } $.ajax({ url: aveabspath + 'index.php?ajax=1', type: 'POST', data: formData, processData: false, contentType: false, xhr: function() { var xhr = new window.XMLHttpRequest(); xhr.upload.addEventListener("progress", function(evt) { if (evt.lengthComputable) { var pct = Math.round((evt.loaded / evt.total) * 100); $('#upload_progress_container').removeClass('d-none'); $('#upload_progress_bar').css('width', pct + '%'); $('#upload_status_text').text(COMMENT_JS_LOADS_F + ' ' + pct + '%'); } }, false); return xhr; }, beforeSend: function() { $btn.prop('disabled', true).text(COMMENT_JS_LOADS_R); }, success: function(data) { if (data.includes('wrong_securecode')) { alert(COMMENT_JS_SEC_CODE_WRONG); getCaptha(); $btn.prop('disabled', false).text(originalBtnText); $('#upload_progress_container').addClass('d-none'); } else { // Очищаем массив перед перезагрузкой newCommentPendingFiles = []; $form[0].reset(); // Чистим текст и инпуты $form.find('input[name="parent_id"]').val('0'); // Сбрасываем "режим ответа" location.reload(); } }, error: function() { alert(COMMENT_JS_ERR_SRV); $btn.prop('disabled', false).text(originalBtnText); $('#upload_progress_container').addClass('d-none'); } }); }); $doc.on('click', '#captcha img, #reload_captcha', function(e) { e.preventDefault(); getCaptha(); }); }); })(jQuery); } })();