Advanced Live Code Editor
`;
const defaultCSS = `body {
font-family: Arial, sans-serif;
margin: 0;
padding: 20px;
background: #f5f6fa;
color: #2d3436;
}
h1 {
color: #6c5ce7;
}`;
const defaultJS = `console.log('Hello from JavaScript!');
document.addEventListener('DOMContentLoaded', function() {
const button = document.createElement('button');
button.textContent = 'Click Me';
button.style.padding = '10px 20px';
button.style.background = '#6c5ce7';
button.style.color = 'white';
button.style.border = 'none';
button.style.borderRadius = '4px';
button.style.cursor = 'pointer';
button.addEventListener('click', function() {
alert('Button clicked!');
});
document.body.appendChild(button);
});`;
const defaultReact = `function App() {
const [count, setCount] = React.useState(0);
return (
React Counter
Count: {count}
);
}
ReactDOM.render(
, document.getElementById('root'));`;
// Initialize editors with default code
htmlEditor.value = defaultHTML;
cssEditor.value = defaultCSS;
jsEditor.value = defaultJS;
reactEditor.value = defaultReact;
// Initialize CodeMirror editors
const editors = {
html: CodeMirror.fromTextArea(htmlEditor, {
mode: 'htmlmixed',
theme: 'dracula',
lineNumbers: true,
autoCloseTags: true,
matchBrackets: true,
autoCloseBrackets: true,
lineWrapping: true,
indentUnit: 4
}),
css: CodeMirror.fromTextArea(cssEditor, {
mode: 'css',
theme: 'dracula',
lineNumbers: true,
matchBrackets: true,
autoCloseBrackets: true,
lineWrapping: true,
indentUnit: 4
}),
js: CodeMirror.fromTextArea(jsEditor, {
mode: 'javascript',
theme: 'dracula',
lineNumbers: true,
matchBrackets: true,
autoCloseBrackets: true,
lineWrapping: true,
indentUnit: 4,
lint: true,
gutters: ['CodeMirror-lint-markers']
}),
react: CodeMirror.fromTextArea(reactEditor, {
mode: 'jsx',
theme: 'dracula',
lineNumbers: true,
matchBrackets: true,
autoCloseBrackets: true,
lineWrapping: true,
indentUnit: 4
})
};
// Set active tab
let activeTab = 'html';
// Tab switching
tabButtons.forEach(button => {
button.addEventListener('click', function() {
// Update active tab
tabButtons.forEach(btn => btn.classList.remove('active'));
this.classList.add('active');
activeTab = this.dataset.tab;
// Show corresponding editor
document.querySelectorAll('.code-editor').forEach(editor => {
editor.classList.remove('active');
});
document.getElementById(`${activeTab}-editor`).classList.add('active');
});
});
// Device view switching
deviceButtons.forEach(button => {
button.addEventListener('click', function() {
deviceButtons.forEach(btn => btn.classList.remove('active'));
this.classList.add('active');
const device = this.dataset.device;
const frame = previewFrame;
switch(device) {
case 'desktop':
frame.style.width = '100%';
responsiveOverlay.style.display = 'none';
break;
case 'tablet':
frame.style.width = '768px';
responsiveOverlay.style.display = 'block';
responsiveOverlay.style.width = '768px';
responsiveOverlay.style.left = 'calc(50% - 384px)';
break;
case 'mobile':
frame.style.width = '375px';
responsiveOverlay.style.display = 'block';
responsiveOverlay.style.width = '375px';
responsiveOverlay.style.left = 'calc(50% - 187.5px)';
break;
}
});
});
// Error handling
let errors = [];
function displayError(error) {
errors.push(error);
errorCount.textContent = errors.length;
const errorItem = document.createElement('div');
errorItem.className = 'error-item';
const errorMessage = document.createElement('div');
errorMessage.className = 'error-message';
errorMessage.textContent = error.message;
const errorLocation = document.createElement('div');
errorLocation.className = 'error-location';
errorLocation.textContent = `Line ${error.line}:${error.column} in ${error.type}`;
errorItem.appendChild(errorMessage);
errorItem.appendChild(errorLocation);
errorList.appendChild(errorItem);
// Open error panel if it's closed
if (!errorPanel.classList.contains('open')) {
errorPanel.classList.add('open');
errorIcon.classList.remove('fa-chevron-up');
errorIcon.classList.add('fa-chevron-down');
}
}
function clearErrors() {
errors = [];
errorCount.textContent = '0';
errorList.innerHTML = '';
}
// Toggle error panel
errorToggle.addEventListener('click', function() {
errorPanel.classList.toggle('open');
if (errorPanel.classList.contains('open')) {
errorIcon.classList.remove('fa-chevron-up');
errorIcon.classList.add('fa-chevron-down');
} else {
errorIcon.classList.remove('fa-chevron-down');
errorIcon.classList.add('fa-chevron-up');
}
});
// Refresh preview
function refreshPreview() {
clearErrors();
try {
const html = editors.html.getValue();
const css = editors.css.getValue();
const js = editors.js.getValue();
const react = editors.react.getValue();
// Create a new document for the iframe
const doc = previewFrame.contentDocument || previewFrame.contentWindow.document;
doc.open();
doc.write(html);
doc.close();
// Inject CSS
const style = doc.getElementById('dynamic-css');
if (style) {
style.textContent = css;
}
// Inject JavaScript
const script = doc.getElementById('dynamic-js');
if (script) {
// Try to evaluate JS first to catch syntax errors
try {
new Function(js);
script.textContent = js;
} catch (jsError) {
displayError({
message: jsError.message,
line: jsError.lineNumber,
column: jsError.columnNumber,
type: 'JavaScript'
});
}
}
// Handle React code
if (react.trim()) {
try {
// Transpile JSX to JS
const transpiled = Babel.transform(react, {
presets: ['react']
}).code;
// Create a script element for React
const reactScript = doc.createElement('script');
reactScript.textContent = `
try {
${transpiled}
} catch (error) {
window.parent.postMessage({
type: 'react-error',
error: {
message: error.message,
line: error.lineNumber,
column: error.columnNumber
}
}, '*');
}
`;
// Add React dependencies
const reactCDN = doc.createElement('script');
reactCDN.src = 'https://unpkg.com/react@17/umd/react.development.js';
reactCDN.crossOrigin = '';
const reactDOMCDN = doc.createElement('script');
reactDOMCDN.src = 'https://unpkg.com/react-dom@17/umd/react-dom.development.js';
reactDOMCDN.crossOrigin = '';
doc.head.appendChild(reactCDN);
doc.head.appendChild(reactDOMCDN);
doc.body.appendChild(reactScript);
} catch (transpileError) {
displayError({
message: transpileError.message,
line: transpileError.loc ? transpileError.loc.line : 1,
column: transpileError.loc ? transpileError.loc.column : 1,
type: 'React'
});
}
}
} catch (error) {
displayError({
message: error.message,
line: error.lineNumber,
column: error.columnNumber,
type: 'HTML'
});
}
}
// Listen for React errors from iframe
window.addEventListener('message', function(event) {
if (event.data.type === 'react-error') {
displayError({
message: event.data.error.message,
line: event.data.error.line,
column: event.data.error.column,
type: 'React'
});
}
});
// Set up auto-refresh with debounce
let debounceTimer;
function debounceRefresh() {
clearTimeout(debounceTimer);
debounceTimer = setTimeout(refreshPreview, 500);
}
// Add change event listeners to all editors
Object.values(editors).forEach(editor => {
editor.on('change', debounceRefresh);
});
// Manual refresh button
refreshBtn.addEventListener('click', refreshPreview);
// Initial refresh
refreshPreview();
});