Skip to main content
39 of 60
Improved the title and meta description tags
Mori
  • 197
  • 1
  • 5
  • 20

Main updates:

  1. Indented code with two spaces rather than four
  2. Changed the download attribute value, myFile.html, to something meaningful: template.html
  3. Combined the preview and createURL functions in a new function
  4. Removed the fileChooser.onclick function: this function is done by the Reset button now.
  5. Added downloader.download = file.name; to the fileChooser.onchange function so the downloader download attribute has the same value as the imported file name. Now there's a logical relationship between the text field content, fileChooser value, and the downloader download attribute value.
  6. In the resize function, changed flex to flexGrow as flexShrink and flexBasis never change
  7. Defined a new task for the Reset button so it not only resets the text field, but also the fileChooser and downloader download attribute values
  8. Added a confirmation message on page exit if the text field is modified
  9. Added a new option: Dark theme; made some code improvements
  10. Added flex-wrap: wrap; to the header and footer so the flex items wrap if necessary
  11. 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.
  12. Now Edge supports outputObject.value — changed indicator.textContent to indicator.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();
Mori
  • 197
  • 1
  • 5
  • 20