17

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

4

3 回答 3

22

这是解决方案的开始:

$(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. 添加自定义粘贴/剪切处理程序以防止右键单击菜单和浏览器菜单剪切/粘贴操作
于 2014-10-17T03:01:28.077 回答
3

您可以通过监听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/

于 2019-02-06T17:25:40.103 回答
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;
}
于 2016-09-23T16:12:33.327 回答