2014-07-25 25 views
15

Korzystając z edytora kodów asów, mogę zablokować lub wykonać fragment kodu tylko do odczytu, ale nadal zezwalać na zapisywanie lub edytowanie innych linii kodu podczas sesji?Edytor asów: Blokuj lub Odczytuj fragment kodu

+0

Potrzebujesz tylko jednego segmentu lub wielu? Czy cały segment może zostać usunięty? Jeśli selekcja obejmuje część tylko do odczytu segmentów, a użytkownik naciśnie przycisk delete, czy resztę zaznaczonego tekstu należy usunąć? –

+0

Też potrzebuję tej funkcji! – ufucuk

Odpowiedz

20

Oto początek rozwiązanie:

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

zobaczyć to działa w tym skrzypce: http://jsfiddle.net/bzwheeler/btsxgena/

Główne elementy pracy są:

  1. tworzyć początek i koniec kotwy ace który śledź lokalizację "tylko do odczytu", gdy zmienia się dokument wokół niej.
  2. utwórz zakres enkapsulacji zakotwiczeń
  3. dodaj niestandardową klawiaturę, aby sprawdzić, czy bieżące zbliżające się naciśnięcie klawisza wpłynie na zakres tylko do odczytu i anulować, jeśli tak.
  4. dodać niestandardowe paste/cut ładowarki do ochrony przed menu i menu przeglądarki kliknij prawym przyciskiem myszy Wytnij/Wklej działań
+0

Mam problem ze zrozumieniem, co się dzieje w funkcji "przed", ale wiem, że "origArgs" nigdy nie jest zdefiniowany i powoduje "preventReadOnly", by wymiotować, gdy próbuje wywołać next() po wycięciu lub wklejeniu. – Southerneer

+0

Dobry połów! Edytowałem implementację before(), aby użyć '.call' i przekazać' args', a nie 'origArgs', które było niezdefiniowane, jak zauważyłeś. – bzwheeler

+0

Co robi tutaj addKeyboardHandler? wyjaśnij pls. – rjohari23

1

Proponuję coś innego łatwiejsze i bardziej wiarygodne, aby zapobiec gamę być modyfikowane (sprawdź to!)

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