create a fully functional ppt editing canvas where i put my html code and think it of like so i have created a presentation agent that will generate ppt using html css js example generated ppt
19e5d94
verified
| // 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 = ` | |
| <i data-feather="${item.icon}"></i> | |
| <span>${item.text}</span> | |
| `; | |
| 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 = ` | |
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| ${document.querySelector('style').outerHTML} | |
| </head> | |
| <body> | |
| ${slideContent.outerHTML} | |
| </body> | |
| </html>`; | |
| // 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!'); | |
| } |