// 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: 15px; right: 15px; background: #ff4757; color: white; border: none; border-radius: 50%; width: 35px; height: 35px; cursor: pointer; z-index: 1; font-size: 18px; font-weight: bold; `; const iframe = document.createElement('iframe'); iframe.src = editorUrl; iframe.style.cssText = ` width: 100%; height: 100%; border: none; border-radius: 8px; `; // Обработчик закрытия const closeModal = () => { document.body.removeChild(modal); window.removeEventListener('message', handleMessage); }; closeBtn.onclick = closeModal; // Обработчик сообщений от редактора const handleMessage = (event) => { if (event.origin !== window.location.origin) return; if (event.data.type === 'imageSelected' && event.data.targetField === fieldName) { inputField.value = event.data.path; // Триггерим события изменения inputField.dispatchEvent(new Event('input', { bubbles: true })); inputField.dispatchEvent(new Event('change', { bubbles: true })); // Обновляем превью если есть updateImagePreview(inputField, event.data.path); closeModal(); } }; window.addEventListener('message', handleMessage); content.appendChild(closeBtn); content.appendChild(iframe); modal.appendChild(content); document.body.appendChild(modal); // Закрытие по клику на фон modal.addEventListener('click', (e) => { if (e.target === modal) { closeModal(); } }); } // Функция обновления превью изображения function updateImagePreview(inputField, imagePath) { const fieldContainer = inputField.closest('.field, .property-edit, div[data-testid]'); 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 && button.nextSibling) { button.parentNode.insertBefore(preview, button.nextSibling); } else { inputField.parentNode.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 hasButton = inputField.parentNode.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(() => { scanAndAddImageButtons(); }); observer.observe(document.body, { childList: true, subtree: true }); // Периодическое сканирование для надежности setInterval(scanAndAddImageButtons, 2000); } // Ждем загрузки DOM if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initialize); } else { initialize(); } // Также запускаем через задержки для AdminJS setTimeout(initialize, 1000); setTimeout(initialize, 3000); setTimeout(initialize, 5000); })();