2014-07-25 20 views
15

Utilizzo di Ace Code Editor è possibile bloccare o rendere in lettura un segmento di codice ma consentire comunque la scrittura o la modifica di altre righe di codice durante una sessione?Ace Editor: Lock o Readonly Segmento di codice

+0

Hai bisogno di un solo segmento o di molti? il segmento completo può essere cancellato? Se la selezione include parte del segmento in sola lettura e l'utente preme eliminare, il resto del testo selezionato dovrebbe essere cancellato? –

+0

Ho anche bisogno di questa funzionalità! – ufucuk

risposta

20

Qui è l'inizio di una soluzione:

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

vederlo lavorare in questo violino: http://jsfiddle.net/bzwheeler/btsxgena/

I principali pezzi di lavoro sono:

  1. creare inizio e ancoraggi ace finali che traccia la posizione di una porzione 'readonly' mentre il documento che lo circonda cambia.
  2. creare un intervallo per incapsulare gli ancoraggi
  3. aggiungere un keyhandler personalizzato per verificare se la pressione del tasto imminente incide sull'intervallo di sola lettura e annullarlo in caso affermativo.
  4. aggiungere i gestori di pasta/tagliati su misura per la protezione contro menu e dei menu del browser azioni taglia/incolla destro del mouse
+0

Non riesco a capire cosa sta succedendo nella funzione "prima", ma so che "origArgs" non è mai definito e causa "preventReadOnly" a vomitare quando tenta di chiamare next() dopo una copia o incolla. – Southerneer

+0

Buona cattura! Ho modificato l'implementazione before() per usare '.call' e per passare 'args' e non' origArgs' che non era definito come notato. – bzwheeler

+0

cosa sta facendo addKeyboardHandler qui? spieghi i pls. – rjohari23

1

suggerisco un'altra cosa più semplice e affidabile per prevenire gamma da modificare (a controllare!)

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