// ===== Mubashra Studio - Advanced Drag & Drop Editor ===== const CORRECT_PASSWORD = "inshaaAllah"; // DOM Elements const authOverlay = document.getElementById('authOverlay'); const adminWorkspace = document.getElementById('adminWorkspace'); const passwordInput = document.getElementById('passwordInput'); const loginBtn = document.getElementById('loginBtn'); const errorMsg = document.getElementById('errorMsg'); const blogCanvas = document.getElementById('blogCanvas'); const canvasWrapper = document.getElementById('canvasWrapper'); const canvasArea = document.getElementById('canvasArea'); const canvasPlaceholder = document.getElementById('canvasPlaceholder'); const blogTitleInput = document.getElementById('blogTitle'); const postBtn = document.getElementById('postBtn'); const previewBtn = document.getElementById('previewBtn'); // Sidebars const sidebarLeft = document.getElementById('sidebarLeft'); const sidebarRight = document.getElementById('sidebarRight'); const sidebarOverlay = document.getElementById('sidebarOverlay'); const menuToggle = document.getElementById('menuToggle'); const closeSidebarLeft = document.getElementById('closeSidebarLeft'); const closeSidebarRight = document.getElementById('closeSidebarRight'); const mobilePropsBtn = document.getElementById('mobilePropsBtn'); // Zoom Controls const zoomIn = document.getElementById('zoomIn'); const zoomOut = document.getElementById('zoomOut'); const zoomReset = document.getElementById('zoomReset'); const zoomLevelDisplay = document.getElementById('zoomLevel'); // Modal Elements const publishModal = document.getElementById('publishModal'); const closeModal = document.getElementById('closeModal'); const cancelPublish = document.getElementById('cancelPublish'); const confirmPublish = document.getElementById('confirmPublish'); const modalBlogTitle = document.getElementById('modalBlogTitle'); const coverUploadArea = document.getElementById('coverUploadArea'); const coverImageInput = document.getElementById('coverImageInput'); const uploadPlaceholder = document.getElementById('uploadPlaceholder'); const uploadPreview = document.getElementById('uploadPreview'); const coverPreviewImg = document.getElementById('coverPreviewImg'); const removeCover = document.getElementById('removeCover'); // Element buttons (both sidebar and mobile) const elementBtns = document.querySelectorAll('.element-btn'); const mobileToolBtns = document.querySelectorAll('.mobile-tool-btn[data-type]'); const layersList = document.getElementById('layersList'); const propertiesPanel = document.getElementById('propertiesPanel'); // Property Panels const textProperties = document.getElementById('textProperties'); const imageProperties = document.getElementById('imageProperties'); const positionProperties = document.getElementById('positionProperties'); // Property Inputs const fontFamily = document.getElementById('fontFamily'); const fontSize = document.getElementById('fontSize'); const fontWeight = document.getElementById('fontWeight'); const textColor = document.getElementById('textColor'); const textColorHex = document.getElementById('textColorHex'); const letterSpacing = document.getElementById('letterSpacing'); const lineHeight = document.getElementById('lineHeight'); const posX = document.getElementById('posX'); const posY = document.getElementById('posY'); const elWidth = document.getElementById('elWidth'); const elHeight = document.getElementById('elHeight'); const elRotation = document.getElementById('elRotation'); const rotationValue = document.getElementById('rotationValue'); const deleteElement = document.getElementById('deleteElement'); // Image Properties const replaceImage = document.getElementById('replaceImage'); const imageBorderRadius = document.getElementById('imageBorderRadius'); const borderRadiusValue = document.getElementById('borderRadiusValue'); const imageOpacity = document.getElementById('imageOpacity'); const opacityValue = document.getElementById('opacityValue'); // Image Upload Input const imageUpload = document.getElementById('imageUpload'); // State let selectedElement = null; let isDragging = false; let isResizing = false; let resizeDirection = ''; let dragStartX = 0; let dragStartY = 0; let initialX = 0; let initialY = 0; let initialWidth = 0; let initialHeight = 0; let elementCounter = 0; let currentZoom = 1; let coverImageData = null; const ZOOM_STEP = 0.1; const MIN_ZOOM = 0.25; const MAX_ZOOM = 2; // ===== Authentication ===== loginBtn.addEventListener('click', checkPassword); passwordInput.addEventListener('keypress', (e) => { if (e.key === 'Enter') checkPassword(); }); function checkPassword() { if (passwordInput.value === CORRECT_PASSWORD) { authOverlay.classList.add('hidden'); adminWorkspace.classList.remove('hidden'); } else { errorMsg.textContent = "Incorrect password. Please try again."; passwordInput.value = ""; passwordInput.focus(); } } // ===== Mobile Sidebar Controls ===== menuToggle?.addEventListener('click', () => { sidebarLeft.classList.add('open'); sidebarOverlay.classList.add('visible'); }); closeSidebarLeft?.addEventListener('click', closeSidebars); closeSidebarRight?.addEventListener('click', closeSidebars); sidebarOverlay?.addEventListener('click', closeSidebars); mobilePropsBtn?.addEventListener('click', () => { sidebarRight.classList.add('open'); sidebarOverlay.classList.add('visible'); }); function closeSidebars() { sidebarLeft.classList.remove('open'); sidebarRight.classList.remove('open'); sidebarOverlay.classList.remove('visible'); } // ===== Zoom Controls ===== zoomIn?.addEventListener('click', () => { if (currentZoom < MAX_ZOOM) { currentZoom = Math.min(currentZoom + ZOOM_STEP, MAX_ZOOM); applyZoom(); } }); zoomOut?.addEventListener('click', () => { if (currentZoom > MIN_ZOOM) { currentZoom = Math.max(currentZoom - ZOOM_STEP, MIN_ZOOM); applyZoom(); } }); zoomReset?.addEventListener('click', () => { currentZoom = 1; applyZoom(); }); function applyZoom() { canvasWrapper.style.transform = `scale(${currentZoom})`; if (zoomLevelDisplay) { zoomLevelDisplay.textContent = `${Math.round(currentZoom * 100)}%`; } } // Mouse wheel zoom canvasArea?.addEventListener('wheel', (e) => { if (e.ctrlKey) { e.preventDefault(); if (e.deltaY < 0 && currentZoom < MAX_ZOOM) { currentZoom = Math.min(currentZoom + ZOOM_STEP, MAX_ZOOM); } else if (e.deltaY > 0 && currentZoom > MIN_ZOOM) { currentZoom = Math.max(currentZoom - ZOOM_STEP, MIN_ZOOM); } applyZoom(); } }, { passive: false }); // ===== Element Creation ===== elementBtns.forEach(btn => { btn.addEventListener('click', () => { const type = btn.dataset.type; createElement(type); closeSidebars(); }); }); mobileToolBtns.forEach(btn => { btn.addEventListener('click', () => { const type = btn.dataset.type; if (type) createElement(type); }); }); function createElement(type, x = 50, y = 50) { elementCounter++; const element = document.createElement('div'); element.classList.add('draggable-element'); element.id = `element-${elementCounter}`; element.dataset.type = type; element.style.left = `${x}px`; element.style.top = `${y}px`; // Create resize handles const handles = ['nw', 'ne', 'sw', 'se', 'n', 's', 'e', 'w']; handles.forEach(dir => { const handle = document.createElement('div'); handle.classList.add('resize-handle', dir); handle.dataset.direction = dir; element.appendChild(handle); }); // Create content based on type const content = document.createElement('div'); content.classList.add('element-content'); switch (type) { case 'h1': content.innerHTML = '

Heading 1

'; element.style.width = '300px'; element.style.minHeight = '60px'; break; case 'h2': content.innerHTML = '

Heading 2

'; element.style.width = '280px'; element.style.minHeight = '50px'; break; case 'h3': content.innerHTML = '

Heading 3

'; element.style.width = '250px'; element.style.minHeight = '40px'; break; case 'p': content.innerHTML = '

Enter your paragraph text here. You can type anything you want.

'; element.style.width = '350px'; element.style.minHeight = '80px'; break; case 'image': // Trigger file upload const uploadHandler = (e) => { const file = e.target.files[0]; if (file) { const reader = new FileReader(); reader.onload = (event) => { content.innerHTML = `Uploaded Image`; element.style.width = '300px'; element.style.height = '200px'; element.appendChild(content); blogCanvas.appendChild(element); setupElementEvents(element); selectElement(element); updateLayersList(); hidePlaceholder(); }; reader.readAsDataURL(file); } imageUpload.value = ''; imageUpload.removeEventListener('change', uploadHandler); }; imageUpload.addEventListener('change', uploadHandler); imageUpload.click(); return; case 'quote': content.innerHTML = '
"Add your inspiring quote here." - Author
'; element.style.width = '350px'; element.style.minHeight = '100px'; break; case 'divider': content.innerHTML = '
'; element.style.width = '300px'; element.style.height = '30px'; break; case 'button': content.innerHTML = 'Click Me'; element.style.width = '120px'; element.style.height = '50px'; break; } element.appendChild(content); blogCanvas.appendChild(element); setupElementEvents(element); selectElement(element); updateLayersList(); hidePlaceholder(); } function setupElementEvents(element) { const type = element.dataset.type; // Helper function to get pointer position const getPointerPos = (e) => { if (e.touches && e.touches.length > 0) { return { x: e.touches[0].clientX, y: e.touches[0].clientY }; } return { x: e.clientX, y: e.clientY }; }; // Mouse/Touch down for dragging const handlePointerDown = (e) => { // Check if it's a resize handle if (e.target.classList.contains('resize-handle')) { startResize(e); return; } selectElement(element); // For text elements, check if we should allow editing const editableEl = e.target.closest('[contenteditable="true"]'); if (editableEl && document.activeElement === editableEl) { return; // Allow text editing } // Start dragging startDrag(e, element); }; element.addEventListener('mousedown', handlePointerDown); element.addEventListener('touchstart', handlePointerDown, { passive: false }); // Double click/tap to edit text element.addEventListener('dblclick', () => { const editable = element.querySelector('[contenteditable="true"]'); if (editable) { editable.focus(); const selection = window.getSelection(); const range = document.createRange(); range.selectNodeContents(editable); selection.removeAllRanges(); selection.addRange(range); } }); // Resize handles - both mouse and touch const handles = element.querySelectorAll('.resize-handle'); handles.forEach(handle => { handle.addEventListener('mousedown', startResize); handle.addEventListener('touchstart', startResize, { passive: false }); }); // Update layers on text input const editables = element.querySelectorAll('[contenteditable="true"]'); editables.forEach(ed => { ed.addEventListener('input', () => { updateLayersList(); }); }); } // ===== Drag Functionality ===== function startDrag(e, element) { if (isResizing) return; e.preventDefault(); isDragging = true; selectedElement = element; element.classList.add('dragging'); const pos = getEventPos(e); dragStartX = pos.x; dragStartY = pos.y; initialX = element.offsetLeft; initialY = element.offsetTop; document.addEventListener('mousemove', drag); document.addEventListener('mouseup', stopDrag); document.addEventListener('touchmove', drag, { passive: false }); document.addEventListener('touchend', stopDrag); } function drag(e) { if (!isDragging || !selectedElement) return; e.preventDefault(); const pos = getEventPos(e); const dx = (pos.x - dragStartX) / currentZoom; const dy = (pos.y - dragStartY) / currentZoom; let newX = initialX + dx; let newY = initialY + dy; // Keep element within canvas bounds newX = Math.max(0, newX); newY = Math.max(0, newY); selectedElement.style.left = `${newX}px`; selectedElement.style.top = `${newY}px`; // Update position inputs if (posX) posX.value = Math.round(newX); if (posY) posY.value = Math.round(newY); } function stopDrag() { if (selectedElement) { selectedElement.classList.remove('dragging'); } isDragging = false; document.removeEventListener('mousemove', drag); document.removeEventListener('mouseup', stopDrag); document.removeEventListener('touchmove', drag); document.removeEventListener('touchend', stopDrag); } // ===== Resize Functionality ===== function startResize(e) { e.stopPropagation(); e.preventDefault(); isResizing = true; resizeDirection = e.target.dataset.direction; const element = e.target.closest('.draggable-element'); selectedElement = element; const pos = getEventPos(e); dragStartX = pos.x; dragStartY = pos.y; initialX = element.offsetLeft; initialY = element.offsetTop; initialWidth = element.offsetWidth; initialHeight = element.offsetHeight; document.addEventListener('mousemove', resize); document.addEventListener('mouseup', stopResize); document.addEventListener('touchmove', resize, { passive: false }); document.addEventListener('touchend', stopResize); } function resize(e) { if (!isResizing || !selectedElement) return; e.preventDefault(); const pos = getEventPos(e); const dx = (pos.x - dragStartX) / currentZoom; const dy = (pos.y - dragStartY) / currentZoom; let newWidth = initialWidth; let newHeight = initialHeight; let newX = initialX; let newY = initialY; if (resizeDirection.includes('e')) { newWidth = Math.max(50, initialWidth + dx); } if (resizeDirection.includes('w')) { newWidth = Math.max(50, initialWidth - dx); newX = initialX + (initialWidth - newWidth); } if (resizeDirection.includes('s')) { newHeight = Math.max(30, initialHeight + dy); } if (resizeDirection.includes('n')) { newHeight = Math.max(30, initialHeight - dy); newY = initialY + (initialHeight - newHeight); } selectedElement.style.width = `${newWidth}px`; selectedElement.style.height = `${newHeight}px`; selectedElement.style.left = `${newX}px`; selectedElement.style.top = `${newY}px`; if (elWidth) elWidth.value = Math.round(newWidth); if (elHeight) elHeight.value = Math.round(newHeight); if (posX) posX.value = Math.round(newX); if (posY) posY.value = Math.round(newY); } function stopResize() { isResizing = false; resizeDirection = ''; document.removeEventListener('mousemove', resize); document.removeEventListener('mouseup', stopResize); document.removeEventListener('touchmove', resize); document.removeEventListener('touchend', stopResize); } // Helper to get event position for both mouse and touch function getEventPos(e) { if (e.touches && e.touches.length > 0) { return { x: e.touches[0].clientX, y: e.touches[0].clientY }; } return { x: e.clientX, y: e.clientY }; } // ===== Selection ===== function selectElement(element) { if (selectedElement && selectedElement !== element) { selectedElement.classList.remove('selected'); } selectedElement = element; element.classList.add('selected'); showPropertiesFor(element); updateLayersList(); } function deselectAll() { if (selectedElement) { selectedElement.classList.remove('selected'); selectedElement = null; } hideAllPropertyPanels(); } blogCanvas.addEventListener('click', (e) => { if (e.target === blogCanvas || e.target === canvasPlaceholder) { deselectAll(); } }); // ===== Properties Panel ===== function showPropertiesFor(element) { const type = element.dataset.type; hideAllPropertyPanels(); if (positionProperties) positionProperties.classList.remove('hidden'); if (posX) posX.value = Math.round(element.offsetLeft); if (posY) posY.value = Math.round(element.offsetTop); if (elWidth) elWidth.value = Math.round(element.offsetWidth); if (elHeight) elHeight.value = Math.round(element.offsetHeight); const transform = element.style.transform; const rotateMatch = transform.match(/rotate\((\d+)deg\)/); if (elRotation) elRotation.value = rotateMatch ? parseInt(rotateMatch[1]) : 0; if (rotationValue) rotationValue.textContent = `${elRotation?.value || 0}°`; if (['h1', 'h2', 'h3', 'p', 'quote', 'button'].includes(type)) { if (textProperties) textProperties.classList.remove('hidden'); const editable = element.querySelector('[contenteditable="true"]') || element.querySelector('.element-button'); if (editable) { const style = window.getComputedStyle(editable); if (fontSize) fontSize.value = parseInt(style.fontSize); if (fontWeight) fontWeight.value = style.fontWeight; const color = rgbToHex(style.color); if (textColor) textColor.value = color; if (textColorHex) textColorHex.value = color; const ls = parseFloat(style.letterSpacing); if (letterSpacing) letterSpacing.value = isNaN(ls) ? 0 : ls; const lh = parseFloat(style.lineHeight) / parseFloat(style.fontSize); if (lineHeight) lineHeight.value = isNaN(lh) ? 1.5 : lh.toFixed(1); } } else if (type === 'image') { if (imageProperties) imageProperties.classList.remove('hidden'); const br = parseInt(element.style.borderRadius) || 0; if (imageBorderRadius) imageBorderRadius.value = br; if (borderRadiusValue) borderRadiusValue.textContent = `${br}px`; const op = parseFloat(element.style.opacity); const opacityPercent = isNaN(op) ? 100 : op * 100; if (imageOpacity) imageOpacity.value = opacityPercent; if (opacityValue) opacityValue.textContent = `${Math.round(opacityPercent)}%`; } if (propertiesPanel) { const emptyMsg = propertiesPanel.querySelector('.empty-properties'); if (emptyMsg) emptyMsg.style.display = 'none'; } } function hideAllPropertyPanels() { if (textProperties) textProperties.classList.add('hidden'); if (imageProperties) imageProperties.classList.add('hidden'); if (positionProperties) positionProperties.classList.add('hidden'); if (propertiesPanel) { const emptyMsg = propertiesPanel.querySelector('.empty-properties'); if (emptyMsg) emptyMsg.style.display = 'block'; } } // ===== Property Change Handlers ===== fontFamily?.addEventListener('change', () => { if (!selectedElement) return; const editable = getEditableElement(); if (editable) editable.style.fontFamily = fontFamily.value; }); fontSize?.addEventListener('input', () => { if (!selectedElement) return; const editable = getEditableElement(); if (editable) editable.style.fontSize = `${fontSize.value}px`; }); fontWeight?.addEventListener('change', () => { if (!selectedElement) return; const editable = getEditableElement(); if (editable) editable.style.fontWeight = fontWeight.value; }); textColor?.addEventListener('input', () => { if (!selectedElement) return; const editable = getEditableElement(); if (editable) editable.style.color = textColor.value; if (textColorHex) textColorHex.value = textColor.value; }); textColorHex?.addEventListener('input', () => { if (!selectedElement) return; const hex = textColorHex.value; if (/^#[0-9A-Fa-f]{6}$/.test(hex)) { if (textColor) textColor.value = hex; const editable = getEditableElement(); if (editable) editable.style.color = hex; } }); letterSpacing?.addEventListener('input', () => { if (!selectedElement) return; const editable = getEditableElement(); if (editable) editable.style.letterSpacing = `${letterSpacing.value}px`; }); lineHeight?.addEventListener('input', () => { if (!selectedElement) return; const editable = getEditableElement(); if (editable) editable.style.lineHeight = lineHeight.value; }); document.querySelectorAll('[data-align]').forEach(btn => { btn.addEventListener('click', () => { if (!selectedElement) return; const editable = getEditableElement(); if (editable) editable.style.textAlign = btn.dataset.align; document.querySelectorAll('[data-align]').forEach(b => b.classList.remove('active')); btn.classList.add('active'); }); }); posX?.addEventListener('input', () => { if (selectedElement) selectedElement.style.left = `${posX.value}px`; }); posY?.addEventListener('input', () => { if (selectedElement) selectedElement.style.top = `${posY.value}px`; }); elWidth?.addEventListener('input', () => { if (selectedElement) selectedElement.style.width = `${elWidth.value}px`; }); elHeight?.addEventListener('input', () => { if (selectedElement) selectedElement.style.height = `${elHeight.value}px`; }); elRotation?.addEventListener('input', () => { if (selectedElement) { selectedElement.style.transform = `rotate(${elRotation.value}deg)`; if (rotationValue) rotationValue.textContent = `${elRotation.value}°`; } }); imageBorderRadius?.addEventListener('input', () => { if (selectedElement) { selectedElement.style.borderRadius = `${imageBorderRadius.value}px`; selectedElement.style.overflow = 'hidden'; if (borderRadiusValue) borderRadiusValue.textContent = `${imageBorderRadius.value}px`; } }); imageOpacity?.addEventListener('input', () => { if (selectedElement) { selectedElement.style.opacity = imageOpacity.value / 100; if (opacityValue) opacityValue.textContent = `${imageOpacity.value}%`; } }); replaceImage?.addEventListener('change', (e) => { if (!selectedElement || selectedElement.dataset.type !== 'image') return; const file = e.target.files[0]; if (file) { const reader = new FileReader(); reader.onload = (event) => { const img = selectedElement.querySelector('img'); if (img) img.src = event.target.result; }; reader.readAsDataURL(file); } replaceImage.value = ''; }); deleteElement?.addEventListener('click', () => { if (selectedElement) { selectedElement.remove(); selectedElement = null; hideAllPropertyPanels(); updateLayersList(); checkPlaceholder(); } }); // ===== Layers List ===== function updateLayersList() { const elements = blogCanvas.querySelectorAll('.draggable-element'); if (elements.length === 0) { layersList.innerHTML = '

No elements yet

'; return; } layersList.innerHTML = ''; elements.forEach((el) => { const type = el.dataset.type; const icon = getIconForType(type); const label = getLabelForElement(el, type); const layerItem = document.createElement('div'); layerItem.classList.add('layer-item'); if (el === selectedElement) { layerItem.classList.add('active'); } layerItem.innerHTML = ` ${icon} ${label} `; layerItem.addEventListener('click', () => { selectElement(el); closeSidebars(); }); layersList.appendChild(layerItem); }); } function getIconForType(type) { const icons = { 'h1': 'title', 'h2': 'format_h2', 'h3': 'format_h3', 'p': 'notes', 'image': 'image', 'quote': 'format_quote', 'divider': 'horizontal_rule', 'button': 'smart_button' }; return icons[type] || 'crop_square'; } function getLabelForElement(el, type) { const labels = { 'h1': 'Heading 1', 'h2': 'Heading 2', 'h3': 'Heading 3', 'p': 'Paragraph', 'image': 'Image', 'quote': 'Quote', 'divider': 'Divider', 'button': 'Button' }; const editable = el.querySelector('[contenteditable="true"]'); if (editable) { const text = editable.textContent.trim(); if (text.length > 15) return text.substring(0, 15) + '...'; return text || labels[type]; } return labels[type] || 'Element'; } // ===== Helper Functions ===== function getEditableElement() { if (!selectedElement) return null; return selectedElement.querySelector('[contenteditable="true"]') || selectedElement.querySelector('.element-button') || selectedElement.querySelector('blockquote'); } function rgbToHex(rgb) { if (!rgb) return '#000000'; if (rgb.startsWith('#')) return rgb; const match = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/); if (!match) return '#000000'; const r = parseInt(match[1]).toString(16).padStart(2, '0'); const g = parseInt(match[2]).toString(16).padStart(2, '0'); const b = parseInt(match[3]).toString(16).padStart(2, '0'); return `#${r}${g}${b}`; } function hidePlaceholder() { if (canvasPlaceholder) canvasPlaceholder.classList.add('hidden'); } function checkPlaceholder() { const elements = blogCanvas.querySelectorAll('.draggable-element'); if (canvasPlaceholder) { canvasPlaceholder.classList.toggle('hidden', elements.length > 0); } } // ===== Keyboard Shortcuts ===== document.addEventListener('keydown', (e) => { if (!selectedElement) return; const isEditing = document.activeElement.getAttribute('contenteditable') === 'true' || document.activeElement.tagName === 'INPUT'; if ((e.key === 'Delete' || e.key === 'Backspace') && !isEditing) { selectedElement.remove(); selectedElement = null; hideAllPropertyPanels(); updateLayersList(); checkPlaceholder(); e.preventDefault(); } if (['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(e.key) && !isEditing) { const step = e.shiftKey ? 10 : 1; switch (e.key) { case 'ArrowUp': selectedElement.style.top = `${selectedElement.offsetTop - step}px`; break; case 'ArrowDown': selectedElement.style.top = `${selectedElement.offsetTop + step}px`; break; case 'ArrowLeft': selectedElement.style.left = `${selectedElement.offsetLeft - step}px`; break; case 'ArrowRight': selectedElement.style.left = `${selectedElement.offsetLeft + step}px`; break; } if (posX) posX.value = Math.round(selectedElement.offsetLeft); if (posY) posY.value = Math.round(selectedElement.offsetTop); e.preventDefault(); } }); // ===== Publish Modal ===== postBtn?.addEventListener('click', () => { const elements = blogCanvas.querySelectorAll('.draggable-element'); if (elements.length === 0) { alert('Canvas is empty! Add some elements before publishing.'); return; } // Show modal if (modalBlogTitle) modalBlogTitle.value = blogTitleInput?.value || ''; publishModal.classList.remove('hidden'); }); closeModal?.addEventListener('click', closePublishModal); cancelPublish?.addEventListener('click', closePublishModal); publishModal?.querySelector('.modal-backdrop')?.addEventListener('click', closePublishModal); function closePublishModal() { publishModal.classList.add('hidden'); coverImageData = null; if (uploadPlaceholder) uploadPlaceholder.classList.remove('hidden'); if (uploadPreview) uploadPreview.classList.add('hidden'); } // Cover Image Upload coverUploadArea?.addEventListener('click', () => { coverImageInput?.click(); }); coverImageInput?.addEventListener('change', (e) => { const file = e.target.files[0]; if (file) { const reader = new FileReader(); reader.onload = (event) => { coverImageData = event.target.result; if (coverPreviewImg) coverPreviewImg.src = coverImageData; if (uploadPlaceholder) uploadPlaceholder.classList.add('hidden'); if (uploadPreview) uploadPreview.classList.remove('hidden'); }; reader.readAsDataURL(file); } }); removeCover?.addEventListener('click', (e) => { e.stopPropagation(); coverImageData = null; if (coverImageInput) coverImageInput.value = ''; if (uploadPlaceholder) uploadPlaceholder.classList.remove('hidden'); if (uploadPreview) uploadPreview.classList.add('hidden'); }); // Confirm Publish confirmPublish?.addEventListener('click', () => { const title = modalBlogTitle?.value || blogTitleInput?.value || 'Untitled Blog'; // Clone canvas for saving const clone = blogCanvas.cloneNode(true); // Clean up cloned elements clone.querySelectorAll('.draggable-element').forEach(el => { el.classList.remove('selected', 'dragging'); el.querySelectorAll('.resize-handle').forEach(h => h.remove()); el.querySelectorAll('[contenteditable]').forEach(c => { c.removeAttribute('contenteditable'); }); el.style.cursor = 'default'; }); const placeholder = clone.querySelector('.canvas-placeholder'); if (placeholder) placeholder.remove(); // Create blog data const blogData = { id: Date.now(), title: title, date: new Date().toISOString(), content: clone.innerHTML, coverImage: coverImageData || null, backgroundColor: '#FFFFFF' }; // Save to localStorage // Save to localStorage const blogs = JSON.parse(localStorage.getItem('mubashra_blogs_v2')) || []; blogs.unshift(blogData); localStorage.setItem('mubashra_blogs_v2', JSON.stringify(blogs)); alert('Blog published successfully!'); // Clear canvas blogCanvas.querySelectorAll('.draggable-element').forEach(el => el.remove()); if (blogTitleInput) blogTitleInput.value = ''; selectedElement = null; hideAllPropertyPanels(); updateLayersList(); checkPlaceholder(); closePublishModal(); }); // Preview previewBtn?.addEventListener('click', () => { const elements = blogCanvas.querySelectorAll('.draggable-element'); if (elements.length === 0) { alert('Canvas is empty! Add some elements to preview.'); return; } const clone = blogCanvas.cloneNode(true); clone.querySelectorAll('.draggable-element').forEach(el => { el.classList.remove('selected', 'dragging'); el.querySelectorAll('.resize-handle').forEach(h => h.remove()); el.querySelectorAll('[contenteditable]').forEach(c => { c.removeAttribute('contenteditable'); }); el.style.cursor = 'default'; }); const placeholder = clone.querySelector('.canvas-placeholder'); if (placeholder) placeholder.remove(); const previewWindow = window.open('', '_blank'); previewWindow.document.write(` Preview - ${blogTitleInput?.value || 'Untitled Blog'}
${clone.innerHTML}
`); previewWindow.document.close(); }); // Initialize updateLayersList();