Files
comment/js/comment.js

889 lines
42 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* ====================================================================
ОБЕРТКА ДЛЯ ОЖИДАНИЯ 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);
// --- ИЗМЕНЕНИЕ 1: Проверка режима редактирования ---
var isEditing = $('#comment_wrapper_' + cid).find('.edit-form-container').length > 0;
if (!isEditing) {
// Находим кнопки управления
var $controls = $('#controls_' + cid); // Убедитесь, что у контейнера кнопок есть такой ID
if ($controls.length) {
$controls.fadeOut(300, function() { $(this).remove(); });
}
// Обновляем статус визуально
$('#timer_container_' + cid).html('<span class="text-danger small"><i class="bi bi-clock-history"></i> Время на правку истекло</span>');
} else {
// Если открыта форма редактирования, просто меняем текст, не удаляя кнопки
$('#timer_container_' + cid).html('<span class="text-warning small fw-bold"><i class="bi bi-exclamation-triangle"></i> Время вышло! Завершите правку.</span>');
}
// --- КОНЕЦ ИЗМЕНЕНИЯ 1 ---
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;
// Получаем настройки из шаблона (те переменные, что мы добавили в тег script)
var allowedExts = (typeof ALLOWED_EXTENSIONS !== 'undefined') ? ALLOWED_EXTENSIONS.toLowerCase().split(',') : ['jpg', 'jpeg', 'png', 'gif'];
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('Тип файла .' + fileExt + ' не разрешен.').removeClass('d-none');
return false;
}
// Проверка размера
if (fileSizeKb > maxSizeKb) {
$errorDisplay.text('Файл слишком большой (' + Math.round(fileSizeKb) + ' Кб). Максимум: ' + maxSizeKb + ' Кб').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('<div class="invalid-feedback">' + msg + '</div>');
}
isValid = false;
} else {
$el.removeClass('is-invalid');
$el.next('.invalid-feedback').remove();
}
}
// Проверка Имени
setInvalid($(form.comment_author_name), !form.comment_author_name.value.trim(), "Введите ваше имя");
// Проверка Email
setInvalid($(form.comment_author_email), !form.comment_author_email.value.trim(), "Введите корректный Email");
// Проверка Доп. поля №1 (если оно обязательное)
if (typeof REQ_F1 !== 'undefined' && REQ_F1 == '1') {
var f1 = $('#in_author_website');
setInvalid(f1, !f1.val().trim(), "Заполните: " + NAME_F1);
}
// Проверка Доп. поля №2 (если оно обязательное)
if (typeof REQ_F2 !== 'undefined' && REQ_F2 == '1') {
var f2 = $('#in_author_city');
setInvalid(f2, !f2.val().trim(), "Заполните: " + NAME_F2);
}
// Проверка Текста
setInvalid($(form.comment_text), !form.comment_text.value.trim(), "Введите текст комментария");
// Проверка файлов в основной форме (Мультизагрузка)
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('<i class="bi bi-lock-fill me-1"></i> ' + 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('<i class="bi bi-unlock-fill me-1"></i> ' + 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 isLock = (action === 'lock');
$btn.toggleClass('mod_comment_lock mod_comment_unlock text-dark text-success')
.attr('title', isLock ? 'Разблокировать' : 'Заблокировать')
.find('i').toggleClass('bi-lock-fill bi-unlock-fill');
}
});
}
/* --- ИНИЦИАЛИЗАЦИЯ --- */
$(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(); });
});
// Счетчик: Количество оставшихся символов 1000 для формы создания комментария
$('#in_message').limit(1000, '#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 = `
<div class="position-relative preview-item">
<img src="${e.target.result}" class="img-thumbnail" style="max-height: 100px; min-width: 100px; object-fit: cover;">
<button type="button" class="btn btn-danger btn-sm position-absolute top-0 end-0 remove-new-img"
style="padding: 0 5px; margin: 2px;" title="Удалить">
<i class="bi bi-x-lg"></i>
</button>
</div>`;
$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(); // Скрываем и полностью очищаем блок превью
// Строка с #image_preview_img больше не нужна, так как картинок теперь много
});
// удаление картинок по одной (крестиком на самой картинке)
$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(1000);
$('.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('<span class="text-success small fw-bold">Спасибо!</span>');
setTimeout(function(){ location.reload(); }, 1000);
} else if (res.indexOf('already_voted') !== -1) {
alert('Вы уже голосовали за этот комментарий.');
} else if (res.indexOf('own_comment') !== -1) {
alert('Нельзя голосовать за свой собственный комментарий.');
} else if (res.indexOf('forbidden_anon') !== -1) {
alert('Голосование доступно только зарегистрированным пользователям.');
} else {
alert('Ошибка при обработке голоса сервером.');
}
},
error: function(xhr) { alert('Ошибка связи с сервером. Статус: ' + 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('Удалить этот комментарий?')) cAction(this, 'delete');
});
// Блокировка
$doc.off('click', '.mod_comment_lock, .mod_comment_unlock').on('click', '.mod_comment_lock, .mod_comment_unlock', function(e) {
e.preventDefault();
cAction(this, $(this).hasClass('mod_comment_lock') ? 'lock' : 'unlock');
});
// НАЧАЛО $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(/<br\s*\/?>/mg, "\n").trim();
// --- СБОР ТЕКУЩИХ КАРТИНОК (ТОЧНЫЙ ПОИСК ПО КОНТЕЙНЕРУ) ---
var existingImagesHtml = '';
// Ищем картинки строго внутри контейнера вложений конкретного комментария
var $imageContainer = $('#image_container_' + cid);
var $foundImgs = $imageContainer.find('img');
if ($foundImgs.length > 0) {
existingImagesHtml = '<div class="d-flex flex-wrap gap-2 mb-3" style="border: 1px dashed #ccc; padding: 10px; background: #fff; border-radius: 8px;">';
$foundImgs.each(function(index) {
var imgSrc = $(this).attr('src');
if (!imgSrc) return;
// Извлекаем имя файла из пути для передачи на сервер
var fileName = imgSrc.split('/').pop();
existingImagesHtml += `
<div id="existing_wrapper_${cid}_${index}" class="position-relative">
<img src="${imgSrc}" class="img-thumbnail" style="width: 80px; height: 80px; object-fit: cover;">
<button type="button" class="btn btn-danger btn-sm position-absolute top-0 end-0 remove-existing-img"
data-id="${cid}"
data-img-path="${fileName}"
data-target="existing_wrapper_${cid}_${index}"
style="padding: 0 5px; margin: 2px; line-height: 1; z-index: 10;"
title="Удалить">
<i class="bi bi-x-lg" style="font-size: 0.8rem;"></i>
</button>
</div>`;
});
existingImagesHtml += '</div>';
}
// --- РЕЙТИНГ (ВОЗВРАЩЕНА ПОЛНАЯ ОРИГИНАЛЬНАЯ ЛОГИКА) ---
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 += `<i class="star-choice ${starClass}" data-value="${i}" style="cursor: pointer; color: #ffc107; font-size: 1.2rem; margin-right: 2px;"></i>`;
}
starsEditBlock = `
<div class="mb-2 rating-edit-block">
<label class="small text-muted d-block mb-1">Ваша оценка:</label>
<div class="d-flex align-items-center">
<div id="user_rating_stars_${cid}">${starsHtml}</div>
<a href="javascript:void(0);" class="reset-edit-stars ms-3 text-decoration-none small text-muted" data-id="${cid}">
<i class="bi bi-x-circle"></i> Сбросить
</a>
</div>
<input type="hidden" name="comment_user_rating" id="rating_input_${cid}" value="${currentRating}" />
</div>`;
}
}
// --- СБОРКА ФОРМЫ ---
var editHtml = `
<div class="edit-form-container border rounded p-3 bg-light mt-2 mb-2">
<textarea rows="5" id="ta_${cid}" class="form-control mb-3">${cleanText}</textarea>
${starsEditBlock}
<p class="small text-muted mb-1">Загруженные файлы:</p>
${existingImagesHtml}
<div class="mb-2">
<label class="small text-muted mb-1">Добавить новые:</label>
<input type="file" name="comment_image[]" id="new_file_${cid}" class="form-control form-control-sm" accept="image/*" multiple>
</div>
<input type="hidden" name="delete_files" id="delete_files_${cid}" value="">
<div class="d-flex gap-2 mt-3 align-items-center">
<button type="button" class="btn btn-sm btn-primary saveButton" data-id="${cid}">Сохранить</button>
<button type="button" class="btn btn-sm btn-secondary cancelButton">Отмена</button>
<small class="ms-auto text-muted">Осталось: <span id="charsLeft_${cid}"></span></small>
</div>
</div>`;
$textBlock.hide();
$attachedImagesBlock.hide();
$foundImgs.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 $previewContainer = $('#new_files_preview_' + cid);
if ($previewContainer.length === 0) {
$(this).after(`<div id="new_files_preview_${cid}" class="d-flex flex-wrap gap-2 mt-2"></div>`);
$previewContainer = $('#new_files_preview_' + cid);
}
// Мы НЕ удаляем старые превью ($previewContainer.empty() убрали),
// а просто добавляем новые в массив и в контейнер
if (files) {
$.each(files, function(i, file) {
if (!file.type.match('image.*')) return;
// Добавляем файл в наш список
pendingFiles.push(file);
var currentIndex = pendingFiles.length - 1;
var reader = new FileReader();
reader.onload = function(e) {
$previewContainer.append(`
<div class="position-relative new-file-item" data-index="${currentIndex}">
<img src="${e.target.result}" class="img-thumbnail" style="width: 80px; height: 80px; object-fit: cover; border: 2px solid #0d6efd;">
<span class="badge bg-primary position-absolute top-0 start-0 m-1" style="font-size: 0.6rem;">NEW</span>
<button type="button" class="btn btn-danger btn-sm position-absolute top-0 end-0 remove-new-file"
style="padding: 0 5px; margin: 2px; line-height: 1; z-index: 10;">
<i class="bi bi-x-lg" style="font-size: 0.7rem;"></i>
</button>
</div>`);
};
reader.readAsDataURL(file);
});
}
// Очищаем инпут, чтобы браузер позволил выбрать те же файлы снова
$(this).val('');
});
// Обработчик удаления НОВОГО файла из превью (до сохранения)
$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();
});
// --- КОНЕЦ ВСТАВКИ ---
// Добавил поддержку лимита символов
if ($.fn.limit) {
$('#ta_' + cid).limit(1000, '#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');
// Добавляем имя файла в скрытый инпут для сервера
var $deleteInput = $('#delete_files_' + cid);
var currentDeleteList = $deleteInput.val() ? $deleteInput.val().split(',') : [];
if (currentDeleteList.indexOf(imgPath) === -1) {
currentDeleteList.push(imgPath);
$deleteInput.val(currentDeleteList.join(','));
}
// Скрываем блок с картинкой
$('#' + targetId).fadeOut(300);
});
// Обработка выбора НОВОГО файла при редактировании
$doc.on('change', 'input[id^="new_file_"]', function() {
var cid = $(this).attr('id').replace('new_file_', '');
var input = this;
var $errorBox = $('#file_error_' + cid);
var $previewWrapper = $('#edit_preview_wrapper_' + cid);
// Очищаем превью перед новым выбором
$previewWrapper.find('.preview-item-new').remove();
$errorBox.addClass('d-none').text('');
if (input.files && input.files.length > 0) {
$previewWrapper.removeClass('d-none');
Array.from(input.files).forEach(function(file) {
if (checkFileConsistency(file, $errorBox)) {
var reader = new FileReader();
reader.onload = function(e) {
// Создаем новое превью для каждого файла
var item = `
<div class="position-relative preview-item-new">
<img src="${e.target.result}" class="img-thumbnail" style="max-height: 100px;">
</div>`;
$previewWrapper.append(item);
}
reader.readAsDataURL(file);
}
});
// Прячем старое фото и помечаем на удаление
$('#existing_preview_wrapper_' + cid).addClass('d-none');
$('#del_img_' + cid).prop('checked', true);
}
});
// Удаление НОВОГО выбранного файла в режиме редактирования
$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_"]');
// 1. Возвращаем текст
$wrapper.find('.mod_comment_text').show();
// 2. Возвращаем оригинальный блок с картинками
// Ищем все возможные варианты названий блоков, которые мы скрывали
$wrapper.find('.mod_comment_attached_image, .comment-files, .attached-images').show();
// 3. Если мы скрывали изображения напрямую через $foundImgs.hide(), показываем их
$wrapper.find('img').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);
// Проверь, есть ли у тебя эти ID в HTML, если нет - прогресс-бар просто не покажется
$('#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'); // добавили переменную для ошибок
if (files) {
$.each(files, function(i, file) {
// --- ТВОЯ ВАЛИДАЦИЯ (Screenshot 7 и 8) ---
if (typeof checkFileConsistency === 'function') {
if (!checkFileConsistency(file, $errorDisplay)) {
return true; // если файл плохой - пропускаем его
}
}
// ------------------------------------------
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;
$previewWrapper.removeClass('d-none'); // показываем только когда есть что показать
$previewWrapper.append(`
<div class="position-relative new-comment-file-item" data-index="${currentIndex}">
<img src="${e.target.result}" class="img-thumbnail" style="width: 80px; height: 80px; object-fit: cover; border: 2px solid #198754;">
<button type="button" class="btn btn-danger btn-sm position-absolute top-0 end-0 remove-new-comment-img"
style="padding: 0 5px; margin: 2px; line-height: 1;">
<i class="bi bi-x-lg" style="font-size: 0.7rem;"></i>
</button>
</div>`);
};
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; // Помечаем удаленным
$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('Загрузка: ' + pct + '%');
}
}, false);
return xhr;
},
beforeSend: function() { $btn.prop('disabled', true).text('Отправка...'); },
success: function(data) {
if (data.includes('wrong_securecode')) {
alert("Код капчи введен неверно!");
getCaptha();
$btn.prop('disabled', false).text(originalBtnText);
$('#upload_progress_container').addClass('d-none');
} else {
// Очищаем массив перед перезагрузкой
newCommentPendingFiles = [];
location.reload();
}
},
error: function() {
alert("Ошибка связи с сервером");
$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);
}
})();