JSFiddle - React, Tailwind, and code Playground

by William Green

HTML

<div id="menu">
  <div class="menuItem">
    <div class="menuOpenButton">File</div>
    <div class="subMenu">
      <div class="selectItem">Open<span class="modifierKeys"><span data-control></span>+O</span>
      </div>
      <div class="selectItem" onclick="editorObj.save();">Save<span class="modifierKeys"><span data-control></span>+S</span>
      </div>
      <div class="selectItem">New<span class="modifierKeys"><span data-control></span>+N</span>
      </div>
      <div class="selectItem">Print<span class="modifierKeys"><span data-control></span>+P</span>
      </div>
      <div class="selectItem" onclick="editorObj.saveAs();">Save As<span class="modifierKeys"><span data-alt></span>+S</div>
      <div class="selectItem" onclick="editorObj.uploadFile();">Upload File<span class="modifierKeys"><span data-alt></span>+O</span>
      </div>
    </div>
  </div>
  <div class="menuItem">
    <div class="menuOpenButton">Edit</div>
    <div class="subMenu">
      <div class="selectItem">Copy<span class="modifierKeys"><span data-control></span>+C</span>
      </div>
      <div class="selectItem">Paste<span class="modifierKeys"><span data-control></span>+V</span>
      </div>
      <div class="selectItem">Select All<span class="modifierKeys"><span data-control></span>+A</span>
      </div>
    </div>
  </div>
  <div class="menuItem">
    <div class="menuOpenButton">Settings</div>
  </div>
  <div class="menuItem">
    <div class="menuOpenButton">View</div>
    <div class="subMenu">
      <div class="selectItem">Theme</div>
      <div class="selectItem">Font</div>
    </div>
  </div>
  <div class="menuItem">
    <div class="menuOpenButton">Live</div>
    <div class="subMenu">
      <div class="selectItem">Open Live Preview<span class="modifierKeys"><span data-control></span>+L</span>
      </div>
      <div class="selectItem">Run<span class="modifierKeys"><span data-control></span>+R</span>
      </div>
      <hr>
      <div class="selectItem">Share</div>
    </div>
 ...

CSS

/*@import url(https://fonts.googleapis.com/css?family=Source+Code+Pro);*/


/*@import url(../fonts/DejaVuSansMono.ttf);*/


/* latin-ext */

@font-face {
  font-family: code;
  font-weight: 200;
  src: url('../../fonts/DejaVuSansMono.ttf');
}

#menu {
  width: 100%;
  display: table;
  position: relative;
  z-index: 10000;
  font-size: 0;
  background-color: #333;
}

#menu .menuItem .menuOpenButton {
  padding-left: 6px;
  padding-right: 6px;
  padding-bottom: 6px;
  padding-top: 6px;
  font-size: 0.8rem;
  position: relative;
  z-index: 900000000000000000;
  background-color: #333;
}

#menu .menuItem {
  color: #fff;
  display: inline-block;
  cursor: default;
}

#menu .menuItem .subMenu {
  display: none;
  background-color: #333;
  position: absolute;
  background-color: #eee;
  border-bottom-right-radius: 2px;
  border-bottom-left-radius: 2px;
  min-width: 150px;
}

#menu .menuItem .subMenu .selectItem:last-child {
  border-bottom-right-radius: 2px;
  border-bottom-left-radius: 2px;
}

#menu .menuItem .subMenu .selectItem {
  color: #333;
  padding: 8px 5px;
  font-size: 0.8rem;
  -o-box-sizing: border-box;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  -ms-box-sizing: border-box;
  box-sizing: border-box;
}

#menu .menuItem .subMenu .selectItem:hover {
  /*box-shadow:0px 0px 10px #9BCDFF inset;*/
  box-shadow: 0px 0px 10px #ddd inset;
}

[menuActive] {
  background-color: #ddd !important;
  color: #333 !important;
}

#menu hr {
  border-bottom: 1px inset #ddd;
}

.modifierKeys {
  float: right;
  padding-left: 50px;
}

#documentStatus {
  color: #fff;
  position: absolute;
  top: 0;
  font-size: 1rem;
  -o-box-sizing: border-box;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  -ms-box-sizing: border-box;
  box-sizing: border-box;
  padding: 4px 6px;
  height: 100%;
  left: 50%;
  -o-transform: translate(-50%, 0%);
  -moz-transform: translate(-50%, 0%);
  -webkit-transform: translate(-50%, 0%);
  -ms-transform:...

JavaScript

/*editor method calls and object*/
var editorObj = {
  focus: false,
  theme: "dark",
  highlighted: false,
  forceFocus: false,
  tabLength: 3,
  lineHeight: 20,
  fontSize: 20,
  autoChars: [
    [39, 39, '#FF645F'],
    [123, 125, '#B473FF'],
    [91, 93, '#91FF69'],
    [60, 62, '#FFCE46'],
    [40, 41, '#FF8450'],
    [34, 34, '#3240FF']
  ], //opening code followed by closing code (sub arrays)
  //autoColors:['#FF645F','#B473FF','#91FF69','#FFCE46','#FF8450','#3240FF'],auto complete color highlighting
  pairId: 0,
  saved: true,
  transferring: false,
  hasFocus: function() {
    editorCaret.style.display = 'inline-block';
  },
  noFocus: function() {
    editorCaret.style.display = 'none';
  },
  removeHighlight: function() {
    var contentElem = editorContent.querySelectorAll('[data-highlight]');
    for (var i = 0; i < contentElem.length; i++) {
      contentElem[i].removeAttribute('data-highlight');
    }
  },
  countLines: function() {
    var fontSize = editorObj.fontSize;
    var codeHeight = editorContent.scrollHeight;
    var lineNum = Math.floor(codeHeight / fontSize);
    var currentLines = parseInt(lineNumbers.getAttribute('data-lines'));
    var numberLag = lineNum - currentLines;
    if (numberLag > 0) {
      //new number
      var number = document.createElement('span');
      number.innerHTML = currentLines + 1;
      lineNumbers.appendChild(number);
      lineNumbers.setAttribute('data-lines', currentLines + 1);
    }
    if (numberLag < 0 && lineNumbers.children.length > 1) {
      //remove number
      lineNumbers.removeChild(lineNumbers.lastChild);
      lineNumbers.setAttribute('data-lines', currentLines - 1);
    }
    resizeEditor();
  },
  scrollToChar: function() {
    if (editorCaret.previousElementSibling) {
      editorCaret.previousElementSibling.scrollIntoView('smooth');
    }
  },
  save: function() {
    editorObj.saved = false;
    if (!editorObj.transferring) {
      //transferring flag
      editorObj.transferring =...