slidecraft-studio / script.js
kirpalsingh2252002's picture
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!');
}