Main updates:
- Indented code with two spaces rather than four
- Changed the
downloadattribute value,myFile.html, to something meaningful:template.html - Combined the
previewandcreateURLfunctions in a new function - Removed the
fileChooser.onclickfunction: this function is done by theResetbutton now. - Added
downloader.download = file.name;to thefileChooser.onchangefunction so thedownloaderdownloadattribute has the same value as the imported file name. Now there's a logical relationship between the text field content,fileChooservalue, and thedownloaderdownloadattribute value. - In the
resizefunction, changedflextoflexGrowasflexShrinkandflexBasisnever change - Defined a new task for the
Resetbutton so it not only resets the text field, but also thefileChooseranddownloaderdownloadattribute values - Added a confirmation message on page exit if the text field is modified
- Added a new option:
Dark theme; made some code improvements - Added
flex-wrap: wrap;to theheaderandfooterso the flex items wrap if necessary - Added a run-stop toggle switch: sometimes you shouldn't run your code until you finish coding or else it will crash your browser. For example, when you're writing loops it can cause an infinite loop.
- Now Edge supports
outputObject.value— changedindicator.textContenttoindicator.value.
Credit:
Special thanks to Schism for his detailed pointers!
Final source code:
HTML Editor: online HTML editor with real-time preview html, body { margin: 0; padding: 0; height: 100%; }body {
display: flex;
flex-direction: column;
}
header,
footer.shown {
display: flex;
flex-wrap: wrap;
align-items: center;
padding: 5px;
}
header {
background: linear-gradient(#FFF, #CCC);
}
label,
#downloader,
[type="button"],
#fileChooser,
output {
font: bold 11px Arial;
color: #333;
}
[type="checkbox"] {
margin: 0 10px 0 5px;
}
#resetter,
#resizer {
margin: 0 5px;
}
#selector {
margin: 0;
}
#fileChooser {
margin: 0 auto 0 5px;
}
#resizer,
iframe {
padding: 0;
}
output {
width: 3.5ch;
margin-right: 10px;
}
#more {
margin: 0;
border: 0;
padding: 0;
background: transparent;
}
#more.on {
border-bottom: 2px solid;
margin-bottom: -2px;
}
main {
flex: 1;
display: flex;
}
main.horizontal {
flex-direction: column;
}
div {
flex-basis: 0;
position: relative;
}
#viewerWrapper {
border-left: 5px solid #CCC;
}
main.horizontal #viewerWrapper {
border-left: 0;
border-top: 5px solid #CCC;
}
div * {
position: absolute;
width: 100%;
height: 100%;
margin: 0;
border: 0;
background: #FFF;
}
textarea {
box-sizing: border-box;
padding: 5px;
outline: 0;
resize: none;
color: #333;
}
textarea.dark {
background: #333;
color: #FFF;
}
footer.shown {
background: linear-gradient(#CCC, #FFF);
}
[title$="Twitter"] {
margin-left: 5px;
margin-right: 5px;
}
img {
display: block;
width: 20px;
height: 20px;
}
address {
margin-left: auto;
font-size: 16px;
font-family: 'Times New Roman';
color: #333;
}
address a {
color: inherit;
}
Run
Download
Editor size
Horizontal view
Dark theme
HTML Document Template
Hello, world!
Feedback | Created by Mori var runner = document.getElementById('runner'), editor = document.getElementById('editor'), downloader = document.getElementById('downloader'), fileChooser = document.getElementById('fileChooser'), resizer = document.getElementById('resizer'), viewsToggler = document.getElementById('viewsToggler'), themesToggler = document.getElementById('themesToggler');function preview() {
if (runner.checked) {
var viewer = document.getElementById('viewer');
try {
var viewerDoc = viewer.contentDocument;
viewerDoc.open();
viewerDoc.write(editor.value);
viewerDoc.close();
} catch (e) { // in case of iframe redirection to a different origin
viewer.src = 'about:blank';
setTimeout(preview, 4); // minimum delay
}
}
}
editor.addEventListener('input', preview);
runner.addEventListener('change', preview);
function createURL() {
var blob = new Blob([editor.value], {
type: 'text/html'
});
downloader.href = window.URL.createObjectURL(blob);
}
editor.addEventListener('change', createURL);
function previewAndCreateURL() {
preview();
createURL();
}
document.getElementById('resetter').addEventListener('click', function() {
if (!editor.value || editor.value != editor.defaultValue && confirm('Your changes will be lost.\nAre you sure you want to reset?')) {
downloader.download = 'template.html';
fileChooser.value = '';
editor.value = editor.defaultValue;
previewAndCreateURL();
} else if (editor.value == editor.defaultValue) {
downloader.download = 'template.html';
fileChooser.value = '';
}
});
document.getElementById('selector').addEventListener('click', function() {
editor.select();
});
fileChooser.addEventListener('change', function() {
var file = this.files[0],
reader = new FileReader();
if (file) { // to ensure that there's a file to read so Chrome, for example, doesn't run this function when you cancel choosing a new file
downloader.download = file.name;
reader.readAsText(file);
reader.addEventListener('load', function() {
editor.value = this.result;
previewAndCreateURL();
});
}
});
function resize() {
var resizerVal = resizer.value;
document.getElementById('editorWrapper').style.flexGrow = resizerVal;
document.getElementById('viewerWrapper').style.flexGrow = 100 - resizerVal;
document.getElementById('indicator').value = (resizerVal / 100).toFixed(2);
}
resizer.addEventListener('input', resize);
function toggleViews() {
var main = document.getElementById('main');
if (viewsToggler.checked) {
main.className = 'horizontal';
} else {
main.className = '';
}
}
viewsToggler.addEventListener('change', toggleViews);
function toggleThemes() {
if (themesToggler.checked) {
editor.className = 'dark';
} else {
editor.className = '';
}
}
themesToggler.addEventListener('change', toggleThemes);
document.getElementById('more').addEventListener('click', function() {
if (this.title == 'More') {
this.title = 'Less';
} else {
this.title = 'More';
}
this.classList.toggle('on');
document.getElementById('footer').classList.toggle('shown');
});
window.addEventListener('beforeunload', function(event) {
if (editor.value && editor.value != editor.defaultValue) {
event.returnValue = 'Your changes may be lost.';
}
});
resize();
toggleViews();
toggleThemes();
previewAndCreateURL();