NodeJs editor

by Julien Roche

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.5/ace.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.5/theme-twilight.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.5/ext-language_tools.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.5/snippets/javascript.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.5/snippets/json.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.5/worker-javascript.js"></script>
<div id="editor">function foo(items) {
   var x = "All this is syntax highlighted";
   return x;
}</div>

CSS

html,
body {
  border: none;
  height: 100%;
  margin: 0 0 0 0;
  padding: 0 0 0 0;
  width: 100%;
}

#editor {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  font-size: 1.25rem;
}

.readonly-highlight{
    background-color: red;
    opacity: 0.2;
    position: absolute;
}

JavaScript 1.7

const editorElement = document.querySelector('#editor');
const Range = require('ace/range').Range;
ace.require('ace/ext/language_tools');

// pass options to ace.edit
const editor = ace.edit(editorElement, {
    mode: 'ace/mode/javascript',
    selectionStyle: 'text'
});

const session = editor.getSession();
session.setTabSize(3);

// use setOptions method to set several options at once
editor.setOptions({
    autoScrollEditorIntoView: true,
    copyWithEmptySelection: true,
    enableBasicAutocompletion: true,
    enableSnippets: true,
    enableLiveAutocompletion: false
});

// some options are also available as methods e.g. 
editor.setTheme('ace/theme/twilight');

editor.keyBinding.addKeyboardHandler({
        handleKeyboard : function(data, hash, keyString, keyCode, event) {
		if (hash === -1 || (keyCode <= 40 && keyCode >= 37)) {
    	return false;
    }

		if (intersects(range)) {
			return {command:'null', passEvent:false};
		}
	}
});

before(editor, 'onPaste', preventReadonly);
before(editor, 'onCut',   preventReadonly);

const range = new Range(1, 0, 1, Infinity);
range.start  = session.doc.createAnchor(range.start);
range.end    = session.doc.createAnchor(range.end);
range.end.$insertRight = true;
session.addMarker(range, 'readonly-highlight');

function before(obj, method, wrapper) {
  var orig = obj[method];
  obj[method] = function() {
    var args = Array.prototype.slice.call(arguments);
    return wrapper.call(this, function(){
      return orig.apply(obj, args);
    }, args);
  }

  return obj[method];
}

function intersects(range) {
  return editor.getSelectionRange().intersects(range);
}

function preventReadonly(next, args) {
  if (intersects(range)) return;
  next();
}