// Global state let currentMode = 'edit'; let selectedElement = null; let isDragging = false; let dragOffset = { x: 0, y: 0 }; // Initialize the application document.addEventListener('DOMContentLoaded', function() { initializeEventListeners(); setupCanvas(); }); function initializeEventListeners() { // Mode buttons document.getElementById('previewMode').addEventListener('click', () => switchMode('preview')); document.getElementById('editMode').addEventListener('click', () => switchMode('edit')); // Load code button document.getElementById('loadCode').addEventListener('click', loadPPT); // Export button document.getElementById('exportBtn').addEventListener('click', exportPPT); // Canvas events document.getElementById('canvasContainer').addEventListener('click', handleCanvasClick); document.addEventListener('keydown', handleKeyDown); document.addEventListener('contextmenu', handleContextMenu); } function setupCanvas() { // Set up initial canvas state const canvas = document.getElementById('canvasContainer'); canvas.addEventListener('mousedown', startDrag); canvas.addEventListener('mousemove', handleDrag); canvas.addEventListener('mouseup', stopDrag); } function switchMode(mode) { currentMode = mode; const previewBtn = document.getElementById('previewMode'); const editBtn = document.getElementById('editMode'); if (mode === 'preview') { previewBtn.classList.remove('bg-gray-200', 'text-gray-700'); previewBtn.classList.add('bg-primary', 'text-white'); editBtn.classList.remove('bg-primary', 'text-white'); editBtn.classList.add('bg-gray-200', 'text-gray-700'); disableEditing(); } else { editBtn.classList.remove('bg-gray-200', 'text-gray-700'); editBtn.classList.add('bg-primary', 'text-white'); previewBtn.classList.remove('bg-primary', 'text-white'); previewBtn.classList.add('bg-gray-200', 'text-gray-700'); enableEditing(); } } function loadPPT() { const codeInput = document.getElementById('codeInput').value; const canvasContainer = document.getElementById('canvasContainer'); if (!codeInput.trim()) { alert('Please enter PPT HTML code'); return; } try { // Clear previous content canvasContainer.innerHTML = ''; // Create iframe to safely render the HTML const iframe = document.createElement('iframe'); iframe.style.width = '100%'; iframe.style.height = '500px'; iframe.style.border = 'none'; iframe.style.borderRadius = '8px'; iframe.onload = function() { // Once iframe is loaded, extract the content and make it editable const iframeDoc = iframe.contentDocument || iframe.contentWindow.document; iframeDoc.open(); iframeDoc.write(codeInput); iframeDoc.close(); // Replace iframe with editable content setTimeout(() => { const slideContent = iframeDoc.body.firstElementChild.cloneNode(true); canvasContainer.innerHTML = ''; canvasContainer.appendChild(slideContent); // Make elements editable makeElementsEditable(slideContent); // Scale the slide to fit container scaleSlideToFit(slideContent); }, 100); }; canvasContainer.appendChild(iframe); } catch (error) { console.error('Error loading PPT:', error); alert('Error loading PPT. Please check your HTML code.'); } } function makeElementsEditable(container) { // Add editable class to all elements const allElements = container.querySelectorAll('*'); allElements.forEach(element => { element.classList.add('editable-element'); // Make text elements directly editable if (element.tagName === 'P' || element.tagName === 'H1' || element.tagName === 'H2' || element.tagName === 'H3' || element.tagName === 'LI' || element.tagName === 'SPAN') { element.setAttribute('contenteditable', 'true'); } // Add event listeners for interaction element.addEventListener('mousedown', handleElementMouseDown); element.addEventListener('dblclick', handleElementDoubleClick); }); } function scaleSlideToFit(slide) { const container = document.getElementById('canvasContainer'); const containerWidth = container.clientWidth; const slideWidth = 1280; // Standard 16:9 slide width if (slideWidth > containerWidth) { const scale = (containerWidth - 40) / slideWidth; slide.style.transform = `scale(${scale})`; slide.style.transformOrigin = 'center top'; } } function handleElementMouseDown(e) { if (currentMode !== 'edit') return; e.stopPropagation(); selectElement(e.target); if (e.target.tagName === 'IMG' || e.target.classList.contains('image-content')) { isDragging = true; const rect = e.target.getBoundingClientRect(); dragOffset.x = e.clientX - rect.left; dragOffset.y = e.clientY - rect.top; } } function handleElementDoubleClick(e) { if (currentMode !== 'edit') return; e.stopPropagation(); const element = e.target; if (element.tagName === 'P' || element.tagName === 'H1' || element.tagName === 'H2' || element.tagName === 'H3' || element.tagName === 'LI') { element.focus(); selectElement(element); } } function startDrag(e) { if (currentMode !== 'edit' || !selectedElement) return; isDragging = true; const rect = selectedElement.getBoundingClientRect(); dragOffset.x = e.clientX - rect.left; dragOffset.y = e.clientY - rect.top; } function handleDrag(e) { if (!isDragging || !selectedElement) return; e.preventDefault(); const container = document.getElementById('canvasContainer'); const containerRect = container.getBoundingClientRect(); const newX = e.clientX - containerRect.left - dragOffset.x; const newY = e.clientY - containerRect.top - dragOffset.y; selectedElement.style.position = 'absolute'; selectedElement.style.left = `${newX}px`; selectedElement.style.top = `${newY}px`; selectedElement.style.zIndex = '1000'; } function stopDrag() { isDragging = false; } function selectElement(element) { // Deselect previous element if (selectedElement) { selectedElement.classList.remove('selected'); } // Select new element selectedElement = element; selectedElement.classList.add('selected'); } function handleCanvasClick(e) { if (e.target === document.getElementById('canvasContainer')) { if (selectedElement) { selectedElement.classList.remove('selected'); selectedElement = null; } } } function handleKeyDown(e) { if (currentMode !== 'edit' || !selectedElement) return; // Delete selected element if (e.key === 'Delete' || e.key === 'Backspace') { e.preventDefault(); selectedElement.remove(); selectedElement = null; } } function handleContextMenu(e) { if (currentMode !== 'edit') return; e.preventDefault(); const element = e.target; if (element.classList.contains('editable-element')) { selectElement(element); showContextMenu(e.clientX, e.clientY, element); } } function showContextMenu(x, y, element) { // Remove existing context menu const existingMenu = document.querySelector('.context-menu'); if (existingMenu) { existingMenu.remove(); } const contextMenu = document.createElement('div'); contextMenu.className = 'context-menu'; contextMenu.style.left = `${x}px`; contextMenu.style.top = `${y}px`; const menuItems = [ { icon: 'edit-3', text: 'Edit Text', action: () => editText(element) }, { icon: 'trash-2', text: 'Delete', action: () => deleteElement(element) }, { icon: 'copy', text: 'Duplicate', action: () => duplicateElement(element) }, { icon: 'layers', text: 'Bring to Front', action: () => bringToFront(element) }, { icon: 'move', text: 'Move to Back', action: () => moveToBack(element) } ]; menuItems.forEach(item => { const menuItem = document.createElement('div'); menuItem.className = 'context-menu-item'; menuItem.innerHTML = ` ${item.text} `; menuItem.addEventListener('click', item.action); contextMenu.appendChild(menuItem); }); document.body.appendChild(contextMenu); feather.replace(); // Close context menu when clicking elsewhere setTimeout(() => { document.addEventListener('click', function closeMenu() { contextMenu.remove(); document.removeEventListener('click', closeMenu); }); }, 10); } function editText(element) { element.focus(); const range = document.createRange(); range.selectNodeContents(element); const selection = window.getSelection(); selection.removeAllRanges(); selection.addRange(range); } function deleteElement(element) { element.remove(); selectedElement = null; } function duplicateElement(element) { const clone = element.cloneNode(true); element.parentNode.insertBefore(clone, element.nextSibling); makeElementsEditable(clone); selectElement(clone); } function bringToFront(element) { element.style.zIndex = '1000'; } function moveToBack(element) { element.style.zIndex = '0'; } function enableEditing() { const editableElements = document.querySelectorAll('.editable-element'); editableElements.forEach(element => { element.style.cursor = 'move'; if (element.tagName === 'P' || element.tagName === 'H1' || element.tagName === 'H2' || element.tagName === 'H3' || element.tagName === 'LI' || element.tagName === 'SPAN') { element.setAttribute('contenteditable', 'true'); } }); } function disableEditing() { const editableElements = document.querySelectorAll('.editable-element'); editableElements.forEach(element => { element.style.cursor = 'default'; element.removeAttribute('contenteditable'); }); } function exportPPT() { const slideContent = document.querySelector('#canvasContainer > *'); if (!slideContent) { alert('No PPT content to export'); return; } const htmlContent = `
${document.querySelector('style').outerHTML} ${slideContent.outerHTML} `; // Create download link const blob = new Blob([htmlContent], { type: 'text/html' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'presentation.html'; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); alert('PPT exported successfully!'); }