Ace Editor: блокировка или только чтение сегмента кода

С помощью редактора кода Ace я могу заблокировать или сделать только для чтения сегмент кода, но все же разрешить писать или редактировать другие строки кода во время сеанса?

2 ответа

Вот начало решения:

$(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. создайте начальный и конечный якоря, которые отслеживают местоположение "только для чтения" части при изменении документа вокруг него.
  2. создать диапазон для инкапсуляции якорей
  3. добавьте пользовательский обработчик ключей, чтобы проверить, повлияет ли текущее предстоящее нажатие на диапазон только для чтения, и отмените его, если это так.
  4. добавить пользовательские обработчики вставки / вырезания для защиты от щелчка правой кнопкой мыши и действий меню вставки / вставки в браузере

Вы можете сделать это легко, слушая 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/

Я предлагаю что-то более простое и надежное, чтобы предотвратить изменение диапазона (проверьте!)

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;
}
Другие вопросы по тегам