I have created a basic HTML editor using a textarea and an iframe to preview HTML, CSS, and JavaScript changes. Here's the setup:
textarea,
iframe {
width: 300px;
height: 200px;
}
<textarea></textarea>
<iframe></iframe>
const textarea = document.querySelector('textarea');
const iframe = document.querySelector('iframe');
function preview() {
const iframeDoc = iframe.contentDocument;
iframeDoc.open();
iframeDoc.write(textarea.value);
iframeDoc.close();
}
textarea.addEventListener('input', preview);
DEMO
The code successfully updates the HTML and CSS content from the textarea into the iframe. However, you can't use JavaScript const or let variables with document.write because it rewrites the entire iframe content, causing a redeclaration error as soon as you edit the inserted code:
Identifier * has already been declared
To reproduce the issue, insert the following sample code into the textarea:
<!doctype html>
<html lang="en">
<head>
<title>Sample Code</title>
</head>
<body>
<p>Hello!</p>
<script>
const p = document.querySelector('p');
p.style.color = 'blue';
</script>
</body>
</html>
Then try changing Hello! to Hello, world!, or blue to red.
What is the best solution to allow users to keep editing the code without encountering this error? Can the try...catch statement be used to handle this specific error, or is there a better approach?
In my opinion, there are two main ways to do this: using the srcdoc attribute (@Kaiido's answer) or using a blob URL. In this answer, I will explain what these options are and how they differ. I will also give you a code example of how to use the blob URL option.
The srcdoc attribute lets you write the HTML content of the iframe as a string. This is easy and simple, but it has some problems:
• Some old browsers do not support the srcdoc attribute, so you may need to provide a fallback using the src attribute.
• The HTML content may contain malicious scripts or links that could compromise the security of your main document. You may need to sanitize or escape the HTML content before assigning it to the srcdoc attribute.
So if you don't mind such problems, you might not need this answer because using a blob URL is more complex and indirect than using srcdoc.
The blob URL method involves creating a new blob object from the HTML content, and then assigning its URL to the src attribute of the iframe. This method can avoid some compatibility and security issues:
• The blob URL is supported by most browsers that support the src attribute, so you do not need to worry about fallbacks.
• The blob URL is separate from the main document and has its own origin and permissions, so it cannot access or modify anything in your main document.
Here is a code example of how to use the blob URL method. I have used a debounce function to avoid updating the iframe too often, which could cause flickering. You can find more information about the debounce function here.
function preview() {
var blob = new Blob([textarea.value], { type: "text/html" });
var url = URL.createObjectURL(blob);
iframe.onload = function () {
URL.revokeObjectURL(url);
};
iframe.src = url;
}
var debounceTimer;
function debounce(func, delay) {
return function () {
clearTimeout(debounceTimer);
debounceTimer = setTimeout(func, delay);
};
}
var debouncedPreview = debounce(preview, 300);
textarea.addEventListener("input", debouncedPreview);
var textarea = document.querySelector("textarea");
var iframe = document.querySelector("iframe");
var debounceTimer;
function debounce(func, delay) {
return function () {
clearTimeout(debounceTimer);
debounceTimer = setTimeout(func, delay);
};
}
function preview() {
var blob = new Blob([textarea.value], { type: "text/html" });
var url = URL.createObjectURL(blob);
iframe.onload = function () {
URL.revokeObjectURL(url);
};
iframe.src = url;
}
var debouncedPreview = debounce(preview, 300);
textarea.addEventListener("input", debouncedPreview);
textarea,
iframe {
width: 400px;
height: 300px;
}
<textarea></textarea>
<iframe src=""></iframe>
In summary, both the srcdoc and the blob URL methods can be used to create a live preview of HTML content in an iframe. The srcdoc method is simpler but less compatible and secure, while the blob URL method is more complex but more compatible and secure. I prefer the blob URL method because it avoids some potential problems with old browsers and malicious content, but you may choose the method that suits your needs and preferences.
Set your iframe's srcdoc instead of reopening its Document:
var textarea = document.querySelector('textarea'),
iframe = document.querySelector('iframe');
function preview() {
iframe.srcdoc = textarea.value;
}
textarea.addEventListener('input', preview);
textarea,
iframe {
width: 400px;
height: 300px;
}
<textarea></textarea>
<iframe></iframe>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With