// JavaScript для интеграции редактора изображений в AdminJS (function() { 'use strict'; // Функция для открытия редактора изображений function openImageEditor(inputField, fieldName) { const currentValue = inputField.value || ''; const editorUrl = `/image-editor-compact.html?field=${fieldName}¤t=${encodeURIComponent(currentValue)}`; // Убираем предыдущие модальные окна document.querySelectorAll('.image-editor-modal').forEach(modal => modal.remove()); // Создаем модальное окно const modal = document.createElement('div'); modal.className = 'image-editor-modal'; modal.style.cssText = ` position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.7); z-index: 10000; display: flex; align-items: center; justify-content: center; `; const content = document.createElement('div'); content.style.cssText = ` background: white; border-radius: 8px; width: 90%; max-width: 700px; height: 80%; max-height: 600px; position: relative; box-shadow: 0 8px 32px rgba(0,0,0,0.3); `; const closeBtn = document.createElement('button'); closeBtn.innerHTML = '✕'; closeBtn.style.cssText = ` position: absolute; top: 10px; right: 10px; background: #ff4757; color: white; border: none; border-radius: 50%; width: 30px; height: 30px; cursor: pointer; z-index: 1; font-size: 16px; font-weight: bold; `; const iframe = document.createElement('iframe'); iframe.src = editorUrl; iframe.style.cssText = ` width: 100%; height: 100%; border: none; border-radius: 8px; `; // Обработчик сообщений от iframe const messageHandler = function(event) { if (event.data.type === 'imageSelected' && event.data.field === fieldName) { console.log('🖼️ Изображение выбрано:', event.data.url); inputField.value = event.data.url; updateImagePreview(inputField, event.data.url); // Триггерим событие change для обновления формы const changeEvent = new Event('change', { bubbles: true }); inputField.dispatchEvent(changeEvent); // Триггерим input событие const inputEvent = new Event('input', { bubbles: true }); inputField.dispatchEvent(inputEvent); modal.remove(); window.removeEventListener('message', messageHandler); } else if (event.data.type === 'editorClosed') { modal.remove(); window.removeEventListener('message', messageHandler); } }; window.addEventListener('message', messageHandler); closeBtn.onclick = function() { modal.remove(); window.removeEventListener('message', messageHandler); }; modal.onclick = function(e) { if (e.target === modal) { modal.remove(); window.removeEventListener('message', messageHandler); } }; content.appendChild(closeBtn); content.appendChild(iframe); modal.appendChild(content); document.body.appendChild(modal); } // Функция обновления превью изображения function updateImagePreview(inputField, imagePath) { const fieldContainer = inputField.closest('.field, .property-edit, div[data-testid]') || inputField.parentNode; if (!fieldContainer) return; // Находим или создаем превью let preview = fieldContainer.querySelector('.image-preview'); if (!preview) { preview = document.createElement('img'); preview.className = 'image-preview'; preview.style.cssText = ` display: block; max-width: 180px; max-height: 120px; object-fit: cover; border: 1px solid #ddd; border-radius: 4px; margin-top: 8px; margin-bottom: 8px; `; // Вставляем превью после кнопки const button = fieldContainer.querySelector('.image-editor-btn'); if (button) { const buttonContainer = button.parentNode; buttonContainer.parentNode.insertBefore(preview, buttonContainer.nextSibling); } else { fieldContainer.appendChild(preview); } } if (imagePath && imagePath.trim()) { preview.src = imagePath + '?t=' + Date.now(); // Добавляем timestamp для обновления preview.style.display = 'block'; preview.onerror = () => { preview.style.display = 'none'; }; } else { preview.style.display = 'none'; } } // Функция добавления кнопки редактора к полю function addImageEditorButton(inputField) { const fieldName = inputField.name || inputField.id || 'image'; // Проверяем, не добавлена ли уже кнопка const fieldContainer = inputField.closest('.field, .property-edit, div[data-testid]') || inputField.parentNode; if (fieldContainer.querySelector('.image-editor-btn')) { return; } // Создаем контейнер для кнопки const buttonContainer = document.createElement('div'); buttonContainer.style.cssText = ` margin-top: 8px; display: flex; align-items: flex-start; gap: 10px; `; // Создаем кнопку const button = document.createElement('button'); button.type = 'button'; button.className = 'image-editor-btn'; button.innerHTML = '📷 Выбрать'; button.style.cssText = ` padding: 6px 12px; background: #007bff; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 13px; white-space: nowrap; `; button.onclick = (e) => { e.preventDefault(); e.stopPropagation(); openImageEditor(inputField, fieldName); }; buttonContainer.appendChild(button); // Добавляем контейнер после поля ввода if (inputField.nextSibling) { inputField.parentNode.insertBefore(buttonContainer, inputField.nextSibling); } else { inputField.parentNode.appendChild(buttonContainer); } // Добавляем превью если есть значение if (inputField.value && inputField.value.trim()) { updateImagePreview(inputField, inputField.value); } // Слушаем изменения в поле для обновления превью inputField.addEventListener('input', () => { updateImagePreview(inputField, inputField.value); }); inputField.addEventListener('change', () => { updateImagePreview(inputField, inputField.value); }); } // Функция проверки, является ли поле полем изображения function isImageField(inputField) { const fieldName = (inputField.name || inputField.id || '').toLowerCase(); let labelText = ''; // Ищем label для поля const fieldContainer = inputField.closest('.field, .property-edit, div[data-testid]'); if (fieldContainer) { const label = fieldContainer.querySelector('label, .property-label, h3'); if (label) { labelText = label.textContent.toLowerCase(); } } // Проверяем по имени поля или тексту label return fieldName.includes('image') || fieldName.includes('photo') || fieldName.includes('avatar') || fieldName.includes('picture') || fieldName.includes('banner') || fieldName.includes('thumbnail') || (fieldName.includes('url') && (labelText.includes('image') || labelText.includes('изображение'))) || labelText.includes('изображение') || labelText.includes('картинка') || labelText.includes('фото') || labelText.includes('image') || labelText.includes('picture'); } // Функция сканирования и добавления кнопок к полям изображений function scanAndAddImageButtons() { console.log('🔍 Сканирование полей для добавления кнопок редактора изображений...'); // Более широкий поиск полей ввода const inputFields = document.querySelectorAll('input[type="text"], input[type="url"], input:not([type="hidden"]):not([type="submit"]):not([type="button"])'); console.log(`📋 Найдено ${inputFields.length} полей ввода`); inputFields.forEach((inputField, index) => { const fieldName = inputField.name || inputField.id || `field_${index}`; const isImage = isImageField(inputField); const fieldContainer = inputField.closest('.field, .property-edit, div[data-testid]') || inputField.parentNode; const hasButton = fieldContainer.querySelector('.image-editor-btn'); console.log(`🔸 Поле "${fieldName}": isImage=${isImage}, hasButton=${!!hasButton}`); if (isImage && !hasButton) { console.log(`➕ Добавляем кнопку для поля "${fieldName}"`); addImageEditorButton(inputField); } }); } // Инициализация при загрузке DOM function initialize() { console.log('🚀 Инициализация селектора изображений AdminJS'); scanAndAddImageButtons(); // Наблюдаем за изменениями в DOM для динамически добавляемых полей const observer = new MutationObserver((mutations) => { let shouldScan = false; mutations.forEach(mutation => { if (mutation.type === 'childList') { mutation.addedNodes.forEach(node => { if (node.nodeType === 1 && (node.tagName === 'INPUT' || node.querySelector('input'))) { shouldScan = true; } }); } }); if (shouldScan) { setTimeout(scanAndAddImageButtons, 100); } }); observer.observe(document.body, { childList: true, subtree: true }); } // Ждем загрузки DOM if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initialize); } else { initialize(); } // Также запускаем через задержки для AdminJS setTimeout(initialize, 1000); setTimeout(initialize, 3000); setTimeout(initialize, 5000); })();