| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341 |
- /*
- 알려진 문제들
- -
- 덜 중요한 문제들
- - layout에 여러 개의 이미지를 한꺼번에 올린 경우에, saveHistory 하지 않음
- - table resize 를 한 후에 saveHistory 하지 않음 / modified+마우스클릭 조합일 때, saveHistory를 하는 로직으로 인해 saveHistory가 될 수 있는 경우가 있음, but 완벽하지 않음
- - backspace / delete 든 여러 번 눌렀을 때에 한 번만 saveHistory하고 싶다.
- */
- Trex.I.History = {};
- Trex.I.History.Standard = {
- getRangeData: function () {
- throw Error("Unimplemented abstract method");
- },
- restoreRange: function (rangeData){
- throw Error("Unimplemented abstract method");
- }
- };
- Trex.I.History.Webkit = {
- getRangeData: function() {
- var p = this.canvas.getProcessor(),
- txSel = p.getTxSel(),
- rangeCount = txSel.getSel().rangeCount;
- var start, end;
- if (rangeCount) {
- var range = txSel.getSel().getRangeAt(0);
- var preSelectionRange = range.cloneRange();
- preSelectionRange.selectNodeContents(this.canvas.getCurrentPanel().getDocument().body);
- preSelectionRange.setEnd(range.startContainer, range.startOffset);
- start = preSelectionRange.toString().length;
- end = start + range.toString().length;
- } else {
- start = 0;
- end = 0;
- }
- return {
- start: start,
- end: end
- };
- },
- restoreRange: function(savedSel){
- var win = this.canvas.getCurrentPanel().getWindow();
- var doc = win.document;
- var containerEl = doc.body;
- var charIndex = 0, range = doc.createRange();
- range.setStart(containerEl, 0);
- range.collapse(true);
- var nodeStack = [containerEl], node, foundStart = false, stop = false;
- while (!stop && (node = nodeStack.pop())) {
- if (node.nodeType == 3) {
- var nextCharIndex = charIndex + node.length;
- if (!foundStart && savedSel.start >= charIndex && savedSel.start <= nextCharIndex) {
- range.setStart(node, savedSel.start - charIndex);
- foundStart = true;
- }
- if (foundStart && savedSel.end >= charIndex && savedSel.end <= nextCharIndex) {
- range.setEnd(node, savedSel.end - charIndex);
- stop = true;
- }
- charIndex = nextCharIndex;
- } else {
- var i = node.childNodes.length;
- while (i--) {
- nodeStack.push(node.childNodes[i]);
- }
- }
- }
- var sel = win.getSelection();
- sel.removeAllRanges();
- sel.addRange(range);
- }
- };
- Trex.I.History.Trident = {
- getRangeData: function() {
- var doc = this.canvas.getCurrentPanel().getDocument();
- var containerEl = doc.body;
- //refactory 필요.
- try{
- var selectedTextRange = doc.selection.createRange();
- }catch(e){
- return {
- start:0,
- end:0
- }
- }
- var preSelectionTextRange = doc.body.createTextRange();
- preSelectionTextRange.moveToElementText(containerEl);
- try {
- preSelectionTextRange.setEndPoint("EndToStart", selectedTextRange);
- var start = preSelectionTextRange.text.length;
- return {
- start: start,
- end: start + selectedTextRange.text.length
- }
- }catch(e){
- }
- var onepoint = preSelectionTextRange.text.length;
- return {
- start: onepoint,
- end: onepoint
- }
- },
- restoreRange: function(savedSel) {
- var doc = this.canvas.getCurrentPanel().getDocument();
- var containerEl = doc.body;
- var textRange = doc.body.createTextRange();
- textRange.moveToElementText(containerEl);
- textRange.collapse(true);
- textRange.moveEnd("character", savedSel.end);
- textRange.moveStart("character", savedSel.start);
- textRange.select();
- }
- };
- /**
- * @fileoverview default history class for redo/undo
- *
- * @author iamdanielkim
- */
- /**
- * @namespace
- */
- (function(){
- function keepMaxLength(list, maxLength) {
- while (list.length >= maxLength) {
- list.shift();
- }
- }
- var MAX_UNDO_COUNT = 20;
- /**
- * @class
- */
- Trex.History = Trex.Class.create({
- $mixins: [
- Trex.I.History.Standard,
- (($tx.msie_nonstd)? Trex.I.History.Trident: Trex.I.History.Webkit)
- ],
- maxUndoCount: MAX_UNDO_COUNT,
- canvas: _NULL,
- undoMementoList: _NULL,
- redoMementoList: _NULL,
- currentMemento: _NULL,
- contentModified: _FALSE,
- initialize: function(canvas){
- this.canvas = canvas;
- this.setupHistory();
- this.bindKeyEvent(canvas);
- },
- bindKeyEvent: function(canvas) {
- var self = this;
- canvas.observeJob('canvas.panel.undo', function() {
- self.undoHandler();
- });
- canvas.observeJob('canvas.panel.redo', function() {
- self.redoHandler();
- });
- },
- setupHistory: function() {
- this.initHistory({ content: $tom.EMPTY_PARAGRAPH_HTML, scrollTop: 0 });
- },
- canUndo: function() {
- return this.undoMementoList.length > 0;
- },
- canRedo: function() {
- return this.redoMementoList.length > 0;
- },
- setCurrentMemento: function(memento) {
- this.currentMemento = memento;
- },
- undoHandler: function() {
- var self = this;
- self.saveHistoryIfEdited();
- if (!self.canUndo()) {
- return;
- }
- var undoMemento = self.undoMementoList.pop();
- undoMemento.undo();
- self.redoMementoList.push(undoMemento);
- self.setCurrentMemento(undoMemento);
- },
- redoHandler: function() {
- var self = this;
- self.saveHistoryIfEdited();
- if (!self.canRedo()) {
- return;
- }
- var redoMemento = self.redoMementoList.pop();
- redoMemento.redo();
- self.undoMementoList.push(redoMemento);
- self.setCurrentMemento(redoMemento);
- },
- initHistory: function(data) {
- var self = this;
- self.undoMementoList = [];
- self.redoMementoList = [];
- var newMemento = new Memento();
- var initialData = Object.extend({ content: $tom.EMPTY_PARAGRAPH_HTML, scrollTop: 0 }, data);
- newMemento.addUndoData(initialData);
- newMemento.addHandler(self.getTextHandler());
- self.setCurrentMemento(newMemento);
- },
- saveHistory: function(before, after, handler) {
- var self = this;
- var undoMementoList = self.undoMementoList;
- var currentMemento = self.currentMemento;
- self.redoMementoList = [];
- if (arguments.length == 3) {
- currentMemento.addUndoRedData(before, after, handler);
- }
- var textData = self.getTextData();
- currentMemento.addRedoData(textData);
- keepMaxLength(undoMementoList, self.maxUndoCount);
- undoMementoList.push(currentMemento);
- var newMemento = new Memento();
- newMemento.addHandler(self.getTextHandler());
- newMemento.addUndoData(textData);
- self.setCurrentMemento(newMemento);
- self.contentModified = _FALSE;
- },
- injectHistory: function(before, after, handler) {
- if (!this.canUndo()) {
- return;
- }
- var undoMementoList = this.undoMementoList;
- var lastMemento = undoMementoList[undoMementoList.length - 1];
- lastMemento.addUndoRedData(before, after, handler);
- },
- saveHistoryIfEdited: function() {
- if (this.contentModified) {
- this.saveHistory();
- }
- },
- saveHistoryByKeyEvent: function(event) {
- var key = {
- code: event.keyCode,
- ctrl: event.ctrlKey || (event.keyCode === 17),
- alt: event.altKey || (event.keyCode === 18),
- shift: event.shiftKey || (event.keyCode === 16)
- };
- if (key.code == 229) { // ignore mouse click in ff.
- return;
- }
- var self = this;
- if (key.code == Trex.__KEY.ENTER || key.code == Trex.__KEY.SPACE || key.code == Trex.__KEY.TAB) {
- self.saveHistoryIfEdited();
- } else if (key.code == Trex.__KEY.DELETE || key.code == Trex.__KEY.BACKSPACE) {
- self.saveHistory();
- } else if ((key.code == Trex.__KEY.PASTE || key.code == Trex.__KEY.CUT) && key.ctrl) {
- self.saveHistory();
- } else if (((key.code > 32 && key.code < 41) && key.shift) || (key.code == 65 && key.ctrl)) { // shift + arrow, home, end, etc.. / select all
- self.saveHistoryIfEdited();
- } else if (key.ctrl || key.alt || (key.shift && key.code == 16)) {
- // content isn't modified
- } else {
- self.contentModified = _TRUE;
- }
- },
- getTextHandler: function() {
- var canvas = this.canvas;
- var self = this;
- return function(data) {
- canvas.setContent(data.content);
- var DEFAULT_RESRORE_RANGE = {start: 0, end: 0};
- var range = data.range || DEFAULT_RESRORE_RANGE;
- self.restoreRange(range);
- if ($tx.msie_nonstd) {
- // #FTDUEDTR-1122
- setTimeout(function() {
- canvas.setScrollTop(data.scrollTop);
- }, 0);
- }
- }
- },
- getTextData:function() {
- return {
- content: this.canvas.getContent(),
- scrollTop: this.canvas.getScrollTop(),
- range: this.getRangeData()
- }
- }
- });
- var Memento = Trex.Class.create({
- initialize: function() {
- this.before = {};
- this.after = {};
- this.handlers = [];
- },
- addUndoRedData: function(before, after, handler) {
- Object.extend(this.before, before);
- Object.extend(this.after, after);
- this.handlers.push(handler);
- },
- addHandler: function(handler) {
- this.handlers.push(handler);
- },
- addUndoData: function(data) {
- Object.extend(this.before, data);
- },
- addRedoData: function(data) {
- Object.extend(this.after, data);
- },
- undo: function() {
- var self = this;
- self.handlers.each(function(handler) {
- handler(self.before);
- });
- },
- redo: function() {
- var self = this;
- self.handlers.each(function(handler) {
- handler(self.after);
- });
- }
- });
- })();
|