Редактор туза: сегмент блокировки или считывания кода

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

Ответы

Ответ 1

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

$(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/

Основными работами являются:

  • создать начальные и конечные анкеры, которые отслеживают местоположение части "только для чтения", когда изменяется документ вокруг него.
  • создать диапазон для инкапсуляции якорей
  • добавьте пользовательский манипулятор, чтобы проверить, повлияет ли текущее надвигающееся нажатие на диапазон readonly и отменит его, если это так.
  • добавить пользовательские дескрипторы палитры/вырезания для защиты от контекстного меню и действий вырезать/вставить меню браузера.

Ответ 2

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

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

Ответ 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/