Spaces:
Running
Running
File size: 3,213 Bytes
18ea57c | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | // DOM elements
const htmlEditor = document.getElementById('html-editor');
const cssEditor = document.getElementById('css-editor');
const jsEditor = document.getElementById('js-editor');
const imageUrlInput = document.getElementById('image-url');
const imageFileInput = document.getElementById('image-file');
const previewIframe = document.getElementById('preview-iframe');
const loadingSpinner = document.getElementById('loading-spinner');
const previewTab = document.getElementById('preview-tab');
const filesTab = document.getElementById('files-tab');
const previewView = document.getElementById('preview-view');
const filesView = document.getElementById('files-view');
// State
let currentImageSrc = '';
let updateTimeout;
// Debounce function
function debounce(func, wait) {
return function executedFunction(...args) {
const later = () => {
clearTimeout(updateTimeout);
func(...args);
};
clearTimeout(updateTimeout);
updateTimeout = setTimeout(later, wait);
};
}
// Update preview function
function updatePreview() {
// Show loading spinner
loadingSpinner.classList.remove('hidden');
// Get current code
let html = htmlEditor.value;
const css = cssEditor.value;
const js = jsEditor.value;
// Replace image src in HTML
html = html.replace(/<img[^>]*id="preview-img"[^>]*>/g, `<img id="preview-img" src="${currentImageSrc}" alt="Your uploaded image">`);
// Build complete HTML document
const fullDoc = `<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>${css}</style>
</head>
<body>
${html}
<script>${js}<\/script>
</body>
</html>`;
// Set iframe content
previewIframe.srcdoc = fullDoc;
// Hide spinner after a short delay
setTimeout(() => {
loadingSpinner.classList.add('hidden');
}, 200);
}
// Debounced update
const debouncedUpdate = debounce(updatePreview, 300);
// Tab switching function
function switchTab(tabButton, viewElement) {
// Remove active class from all tabs
document.querySelectorAll('.tab-button').forEach(btn => btn.classList.remove('active'));
// Add active class to clicked tab
tabButton.classList.add('active');
// Remove active class from all views
document.querySelectorAll('.view').forEach(view => view.classList.remove('active'));
// Add active class to target view
viewElement.classList.add('active');
}
// Event listeners for tabs
previewTab.addEventListener('click', () => switchTab(previewTab, previewView));
filesTab.addEventListener('click', () => switchTab(filesTab, filesView));
// Event listeners for image inputs
imageUrlInput.addEventListener('input', (e) => {
currentImageSrc = e.target.value;
debouncedUpdate();
});
imageFileInput.addEventListener('change', (e) => {
const file = e.target.files[0];
if (file) {
const reader = new FileReader();
reader.onload = (event) => {
currentImageSrc = event.target.result;
debouncedUpdate();
};
reader.readAsDataURL(file);
}
});
// Editor input events
[htmlEditor, cssEditor, jsEditor].forEach(editor => {
editor.addEventListener('input', debouncedUpdate);
});
// Initial preview update
updatePreview(); |