Ace编辑器:锁定或只读代码段

时间:2014-07-25 14:54:41

标签: user-interface editor ace-editor readonly-attribute

使用Ace代码编辑器,我可以锁定或只读一段代码,但仍允许在会话期间编写或编辑其他代码行吗?

3 个答案:

答案 0 :(得分:21)

以下是解决方案的开始:

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

看到它在这个小提琴中工作:http://jsfiddle.net/bzwheeler/btsxgena/

主要工作是:

  1. 创建开始和结束ace锚点,当它周围的文档发生变化时,它会跟踪“只读”部分的位置。
  2. 创建一个封装锚点的范围
  3. 添加自定义键盘处理程序以检查当前即将发生的按键是否会影响只读范围,如果是,则取消它。
  4. 添加自定义粘贴/剪切处理程序以防止右键单击菜单和浏览器菜单剪切/粘贴操作

答案 1 :(得分:1)

我建议更容易和更可靠的其他方法来防止范围被修改(检查它!)

var old$tryReplace = editor.$tryReplace;
editor.$tryReplace = function(range, replacement) {
    return intersects(range)?null:old$tryReplace.apply(this, arguments);                        
}
var session = editor.getSession();
var oldInsert = session.insert;
session.insert = function(position, text) {
    return oldInsert.apply(this, [position, outsideRange(position)?text:""]);
}
var oldRemove = session.remove;
session.remove = function(range) {
    return intersects(range)?false:oldRemove.apply(this, arguments);                        
}
var oldMoveText = session.moveText;
session.moveText = function(fromRange, toPosition, copy) {
    if (intersects(fromRange) || !outsideRange(toPosition)) return fromRange;
    return oldMoveText.apply(this, arguments)
}

outsideRange = function (position) {
    var s0 = range.start;
    if (position.row < s0.row || (position.row == s0.row && position.column <= s0.column)) return true; // position must be before range.start
    var e0 = range.end;
    if (position.row > e0.row || (position.row == e0.row && position.column >= e0.column)) return true; // or after range.end
    return false;
}
intersects = function(withRange) {
    var e = withRange.end, s0 = range.start, s = withRange.start, e0 = range.end;
    if (e.row < s0.row || (e.row == s0.row && e.column <= s0.column)) return false; // withRange.end must be before range.start
    if (s.row > e0.row || (s.row == e0.row && s.column >= e0.column)) return false; // or withRange.start must be after range.end
    return true;
}

答案 2 :(得分:1)

您可以通过监听exec事件来轻松做到这一点:

// Prevent editing first and last line of editor
editor.commands.on("exec", function(e) { 
  var rowCol = editor.selection.getCursor();
  if ((rowCol.row === 0) || ((rowCol.row + 1) === editor.session.getLength())) {
    e.preventDefault();
    e.stopPropagation();
  }
});

来源:https://jsfiddle.net/tripflex/y0huvc1b/