Bhavani Ravi Bhavani Ravi - 2 months ago 40
Javascript Question

How to make multiple chunk of lines readonly in ace editor

I tried to make parts of code read-only in Ace editor.

I have tried by using code given in JsFiddle

$(function() {
var editor = ace.edit("editor1")
, session = editor.getSession()
, Range = require("ace/range").Range
, range = new Range(1, 4, 1, 10)
, markerId = session.addMarker(range, "readonly-highlight");

session.setMode("ace/mode/javascript");
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);

range.start = session.doc.createAnchor(range.start);
range.end = session.doc.createAnchor(range.end);
range.end.$insertRight = true;

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();
}
});


I got a problem when I keep pressing backspace it went into the read-only part and there was no editable part left.

How can I make multiple chunks of code read-only and avoid last character from read-only getting deleted.

Also, how to achieve the whole thing dynamically where I have markers in text specifying editable portions ?

Answer

Check the bellow code.

function refresheditor() {
   document.getElementById("myeditor").innerHTML="<div id='editor'></div>"; document.getElementById("editor").innerHTML=document.getElementById("code").innerHTML;
    var editor     = ace.edit("editor")
        , session  = editor.getSession()
        , Range    = require("ace/range").Range
        , ranges    = [];
        var text= document.getElementById("code").innerHTML.split("\n");
        var starts=[0],ends=[];
        text.forEach(function(line,index){
          if((line.indexOf("&lt;editable&gt;") !== -1))ends.push(index);
          if((line.indexOf("&lt;/editable&gt;") !== -1))starts.push(index+1);
        });
        ends.push(text.length);
        for(i=0;i<starts.length;i++){
          ranges.push(new Range(starts[i], 0,ends[i] ,0));
        }
        ranges.forEach(function(range){session.addMarker(range, "readonly-highlight");});
    session.setMode("ace/mode/javascript");
    editor.keyBinding.addKeyboardHandler({
        handleKeyboard : function(data, hash, keyString, keyCode, event) {
            var pos=editor.getCursorPosition();
            if ((Math.abs(keyCode) == 13) && (ends.indexOf(pos["row"])>=0)&&(pos["column"]==0)) return false;
            if (hash === -1 || (keyCode <= 40 && keyCode >= 37)) return false;
            for(i=0;i<ranges.length;i++){
              if (intersects(ranges[i])) {
                  return {command:"null", passEvent:false};
              }
            }
        }
    });
    before(editor, 'onPaste', preventReadonly);
    before(editor, 'onCut',   preventReadonly);
    for(i=0;i<ranges.length;i++){
      ranges[i].start  = session.doc.createAnchor(ranges[i].start);
      ranges[i].end    = session.doc.createAnchor(ranges[i].end);
      ranges[i].end.$insertRight = true;
     }
    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) {
        for(i=0;i<ranges.length;i++){if (intersects(ranges[i])) return;}
        next();
    }
}
refresheditor();
.ace_editor {
    width:100%;
    height:300px;
}
.readonly-highlight{
    background-color: red;
    opacity: 0.2;
    position: absolute;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ace.c9.io/build/src/ace.js"></script>
<link rel="stylesheet" type="text/css" href="http://jsfiddle.net/css/normalize.css">
<link rel="stylesheet" type="text/css" href="http://jsfiddle.net/css/result-light.css">
  <div id="myeditor" ></div>
  <div id="code" style="display:none;">//&lt;editable&gt;
//&lt;/editable&gt;
    $(window).load(function(){
$(function() {
    var editor     = ace.edit("editor1")
        , session  = editor.getSession()
        , Range    = require("ace/range").Range
        , ranges    = [new Range(1, 0, 3,0),new Range(5, 0, 7,0)];
        ranges.forEach(function(range){session.addMarker(range, "readonly-highlight");});
    session.setMode("ace/mode/javascript");
    editor.keyBinding.addKeyboardHandler({
        handleKeyboard : function(data, hash, keyString, keyCode, event) {
            if (hash === -1 || (keyCode &lt;= 40 && keyCode &gt;= 37)) return false;
            for(i=0;i&lt;ranges.length;i++){
              if (intersects(ranges[i])) {
                  return {command:"null", passEvent:false};
              }
            }
        }
    });
    //&lt;editable&gt;
    before(editor, 'onPaste', preventReadonly);
    before(editor, 'onCut',   preventReadonly);
    for(i=0;i&lt;ranges.length;i++){
      ranges[i].start  = session.doc.createAnchor(range.start);
      range[i].end    = session.doc.createAnchor(range.end);
      range[i].end.$insertRight = true;
     }
     //&lt;/editable&gt;
    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];
    }
    //&lt;editable&gt;
    function intersects(range) {
        return editor.getSelectionRange().intersects(range);
    }
    //&lt;/editable&gt;
    function preventReadonly(next, args) {
        for(i=0;i&lt;ranges.length;i++){if (intersects(ranges[i])) return;}
        next();
    }
});
});
</div>
<button onclick="refresheditor()">Reload</button>