document.addEventListener('DOMContentLoaded', function() { const contentTextarea = document.getElementById('content'); const previewForm = document.getElementById('preview-form'); if (!contentTextarea) return; let isFullscreen = false; let originalStyles = {}; let isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent); initEditor(); function initEditor() { autoResize(); contentTextarea.addEventListener('input', autoResize); contentTextarea.addEventListener('input', processDialogues); contentTextarea.addEventListener('keydown', handleTab); contentTextarea.addEventListener('input', updatePreviewContent); updatePreviewContent(); addControlButtons(); // На мобильных устройствах добавляем обработчик изменения ориентации if (isMobile) { window.addEventListener('orientationchange', function() { if (isFullscreen) { setTimeout(adjustForMobileKeyboard, 300); } }); // Обработчик для виртуальной клавиатуры window.addEventListener('resize', function() { if (isFullscreen && isMobile) { adjustForMobileKeyboard(); } }); } } function autoResize() { if (isFullscreen) return; contentTextarea.style.height = 'auto'; contentTextarea.style.height = contentTextarea.scrollHeight + 'px'; } function processDialogues() { const lines = contentTextarea.value.split('\n'); let changed = false; const processedLines = lines.map(line => { if (line.trim().startsWith('- ') && line.trim().length > 2) { const trimmed = line.trim(); const restOfLine = trimmed.substring(2); if (/^[a-zA-Zа-яА-Я]/.test(restOfLine)) { changed = true; return line.replace(trimmed, `— ${restOfLine}`); } } return line; }); if (changed) { const cursorPos = contentTextarea.selectionStart; contentTextarea.value = processedLines.join('\n'); contentTextarea.setSelectionRange(cursorPos, cursorPos); if (!isFullscreen) autoResize(); } } function handleTab(e) { if (e.key === 'Tab') { e.preventDefault(); const start = contentTextarea.selectionStart; const end = contentTextarea.selectionEnd; contentTextarea.value = contentTextarea.value.substring(0, start) + ' ' + contentTextarea.value.substring(end); contentTextarea.selectionStart = contentTextarea.selectionEnd = start + 4; if (!isFullscreen) autoResize(); } } function updatePreviewContent() { if (previewForm) { document.getElementById('preview-content').value = contentTextarea.value; } } function adjustForMobileKeyboard() { if (!isMobile || !isFullscreen) return; // На мобильных устройствах уменьшаем высоту textarea, чтобы клавиатура не перекрывала контент const viewportHeight = window.innerHeight; const keyboardHeight = viewportHeight * 0.4; // Предполагаемая высота клавиатуры (40% экрана) const availableHeight = viewportHeight - keyboardHeight - 80; // 80px для кнопок и отступов contentTextarea.style.height = availableHeight + 'px'; contentTextarea.style.paddingBottom = '20px'; // Прокручиваем к курсору setTimeout(() => { const cursorPos = contentTextarea.selectionStart; if (cursorPos > 0) { scrollToCursor(); } }, 100); } function scrollToCursor() { const textarea = contentTextarea; const cursorPos = textarea.selectionStart; // Создаем временный элемент для измерения позиции курсора const tempDiv = document.createElement('div'); tempDiv.style.cssText = ` position: absolute; top: -1000px; left: -1000px; width: ${textarea.clientWidth}px; padding: ${textarea.style.padding}; font: ${getComputedStyle(textarea).font}; line-height: ${textarea.style.lineHeight}; white-space: pre-wrap; word-wrap: break-word; visibility: hidden; `; const textBeforeCursor = textarea.value.substring(0, cursorPos); tempDiv.textContent = textBeforeCursor; document.body.appendChild(tempDiv); const textHeight = tempDiv.offsetHeight; document.body.removeChild(tempDiv); // Прокручиваем так, чтобы курсор был виден const lineHeight = parseInt(getComputedStyle(textarea).lineHeight) || 24; const visibleHeight = textarea.clientHeight; const cursorLine = Math.floor(textHeight / lineHeight); const visibleLines = Math.floor(visibleHeight / lineHeight); const targetScroll = Math.max(0, (cursorLine - Math.floor(visibleLines / 3)) * lineHeight); textarea.scrollTop = targetScroll; } function addControlButtons() { const container = contentTextarea.parentElement; const controlsContainer = document.createElement('div'); controlsContainer.className = 'editor-controls'; const fullscreenBtn = createButton('🔲', 'Полноэкранный режим', toggleFullscreen); const helpBtn = createButton('❓', 'Справка по Markdown', showHelp); controlsContainer.appendChild(fullscreenBtn); controlsContainer.appendChild(helpBtn); container.insertBefore(controlsContainer, contentTextarea); function toggleFullscreen() { if (!isFullscreen) { enterFullscreen(); } else { exitFullscreen(); } } function enterFullscreen() { originalStyles = { position: contentTextarea.style.position, top: contentTextarea.style.top, left: contentTextarea.style.left, width: contentTextarea.style.width, height: contentTextarea.style.height, zIndex: contentTextarea.style.zIndex, backgroundColor: contentTextarea.style.backgroundColor, border: contentTextarea.style.border, borderRadius: contentTextarea.style.borderRadius, fontSize: contentTextarea.style.fontSize, padding: contentTextarea.style.padding, margin: contentTextarea.style.margin }; if (isMobile) { // Для мобильных - адаптивный режим с учетом клавиатуры const viewportHeight = window.innerHeight; const availableHeight = viewportHeight - 100; // Оставляем место для кнопок Object.assign(contentTextarea.style, { position: 'fixed', top: '50px', left: '0', width: '100vw', height: availableHeight + 'px', zIndex: '9998', backgroundColor: 'white', border: '2px solid #007bff', borderRadius: '0', fontSize: '18px', padding: '15px', margin: '0', boxSizing: 'border-box', resize: 'none' }); // На мобильных устройствах фокусируем textarea сразу setTimeout(() => { contentTextarea.focus(); }, 300); } else { // Для ПК - классический полноэкранный режим Object.assign(contentTextarea.style, { position: 'fixed', top: '5vh', left: '5vw', width: '90vw', height: '90vh', zIndex: '9998', backgroundColor: 'white', border: '2px solid #007bff', borderRadius: '8px', fontSize: '16px', padding: '20px', margin: '0', boxSizing: 'border-box', resize: 'none' }); } controlsContainer.style.display = 'none'; createFullscreenControls(); isFullscreen = true; document.body.style.overflow = 'hidden'; } function exitFullscreen() { Object.assign(contentTextarea.style, originalStyles); controlsContainer.style.display = 'flex'; removeFullscreenControls(); isFullscreen = false; document.body.style.overflow = ''; autoResize(); } function createFullscreenControls() { const fullscreenControls = document.createElement('div'); fullscreenControls.id = 'fullscreen-controls'; const exitBtn = createButton('❌', 'Выйти из полноэкранного режима', exitFullscreen); const helpBtnFullscreen = createButton('❓', 'Справка по Markdown', showHelp); // Для мобильных увеличиваем кнопки и добавляем отступы const buttonSize = isMobile ? '60px' : '50px'; const fontSize = isMobile ? '24px' : '20px'; const topPosition = isMobile ? '10px' : '15px'; [exitBtn, helpBtnFullscreen].forEach(btn => { btn.style.cssText = ` width: ${buttonSize}; height: ${buttonSize}; border-radius: 50%; border: 1px solid #ddd; background: white; cursor: pointer; font-size: ${fontSize}; display: flex; align-items: center; justify-content: center; box-shadow: 0 2px 5px rgba(0,0,0,0.3); transition: all 0.3s ease; color: #333333; touch-action: manipulation; `; }); fullscreenControls.appendChild(helpBtnFullscreen); fullscreenControls.appendChild(exitBtn); fullscreenControls.style.cssText = ` position: fixed; top: ${topPosition}; right: 10px; z-index: 9999; display: flex; gap: 5px; `; document.body.appendChild(fullscreenControls); // Предотвращаем всплытие событий от кнопок к textarea fullscreenControls.addEventListener('touchstart', function(e) { e.stopPropagation(); }); fullscreenControls.addEventListener('touchend', function(e) { e.stopPropagation(); }); } function removeFullscreenControls() { const fullscreenControls = document.getElementById('fullscreen-controls'); if (fullscreenControls) { fullscreenControls.remove(); } } // Выход по ESC document.addEventListener('keydown', function(e) { if (e.key === 'Escape' && isFullscreen) { exitFullscreen(); } }); // На мобильных устройствах добавляем обработчик для выхода по тапу вне textarea if (isMobile) { document.addEventListener('touchstart', function(e) { if (isFullscreen && !contentTextarea.contains(e.target) && !document.getElementById('fullscreen-controls')?.contains(e.target)) { exitFullscreen(); } }); } // Обработчик фокуса для мобильных устройств if (isMobile) { contentTextarea.addEventListener('focus', function() { if (isFullscreen) { setTimeout(adjustForMobileKeyboard, 100); } }); } } function createButton(icon, title, onClick) { const button = document.createElement('button'); button.innerHTML = icon; button.title = title; button.type = 'button'; const buttonSize = isMobile ? '50px' : '40px'; const fontSize = isMobile ? '20px' : '16px'; button.style.cssText = ` width: ${buttonSize}; height: ${buttonSize}; border-radius: 50%; border: 1px solid #ddd; background: white; cursor: pointer; font-size: ${fontSize}; display: flex; align-items: center; justify-content: center; box-shadow: 0 2px 5px rgba(0,0,0,0.2); transition: all 0.3s ease; color: #333333; touch-action: manipulation; `; button.addEventListener('mouseenter', function() { this.style.transform = 'scale(1.1)'; this.style.backgroundColor = '#f8f9fa'; this.style.boxShadow = '0 4px 8px rgba(0,0,0,0.3)'; }); button.addEventListener('mouseleave', function() { this.style.transform = 'scale(1)'; this.style.backgroundColor = 'white'; this.style.boxShadow = '0 2px 5px rgba(0,0,0,0.2)'; }); button.addEventListener('click', onClick); // Для мобильных устройств button.addEventListener('touchstart', function(e) { e.stopPropagation(); this.style.transform = 'scale(1.1)'; this.style.backgroundColor = '#f8f9fa'; this.style.boxShadow = '0 4px 8px rgba(0,0,0,0.3)'; }); button.addEventListener('touchend', function(e) { e.stopPropagation(); this.style.transform = 'scale(1)'; this.style.backgroundColor = 'white'; this.style.boxShadow = '0 2px 5px rgba(0,0,0,0.2)'; onClick(); }); return button; } function showHelp() { const helpContent = `
Жирный текст: **текст** или __текст__
Наклонный текст: *текст* или _текст_
Подчеркнутый текст: <u>текст</u>
Зачеркнутый текст: ~~текст~~
> Это цитата
> > Вложенная цитата
Автоматическое преобразование:
- Привет! → — Привет!
Дефис в начале строки автоматически заменяется на тире с пробелом
Маркированный список:
Нумерованный список:
Код в строке:
\`код в строке\`
Блок кода:
\`\`\` блок кода многострочный \`\`\`
💡 Подсказка: Используйте кнопку "👁️ Предпросмотр" чтобы увидеть как будет выглядеть готовый текст!