| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298 | /** * undo redo * @file * @since 1.2.6.1 *//** * 撤销上一次执行的命令 * @command undo * @method execCommand * @param { String } cmd 命令字符串 * @example * ```javascript * editor.execCommand( 'undo' ); * ``` *//** * 重做上一次执行的命令 * @command redo * @method execCommand * @param { String } cmd 命令字符串 * @example * ```javascript * editor.execCommand( 'redo' ); * ``` */UE.plugins['undo'] = function () {    var saveSceneTimer;    var me = this,        maxUndoCount = me.options.maxUndoCount || 20,        maxInputCount = me.options.maxInputCount || 20,        fillchar = new RegExp(domUtils.fillChar + '|<\/hr>', 'gi');// ie会产生多余的</hr>    var noNeedFillCharTags = {        ol:1,ul:1,table:1,tbody:1,tr:1,body:1    };    var orgState = me.options.autoClearEmptyNode;    function compareAddr(indexA, indexB) {        if (indexA.length != indexB.length)            return 0;        for (var i = 0, l = indexA.length; i < l; i++) {            if (indexA[i] != indexB[i])                return 0        }        return 1;    }    function compareRangeAddress(rngAddrA, rngAddrB) {        if (rngAddrA.collapsed != rngAddrB.collapsed) {            return 0;        }        if (!compareAddr(rngAddrA.startAddress, rngAddrB.startAddress) || !compareAddr(rngAddrA.endAddress, rngAddrB.endAddress)) {            return 0;        }        return 1;    }    function UndoManager() {        this.list = [];        this.index = 0;        this.hasUndo = false;        this.hasRedo = false;        this.undo = function () {            if (this.hasUndo) {                if (!this.list[this.index - 1] && this.list.length == 1) {                    this.reset();                    return;                }                while (this.list[this.index].content == this.list[this.index - 1].content) {                    this.index--;                    if (this.index == 0) {                        return this.restore(0);                    }                }                this.restore(--this.index);            }        };        this.redo = function () {            if (this.hasRedo) {                while (this.list[this.index].content == this.list[this.index + 1].content) {                    this.index++;                    if (this.index == this.list.length - 1) {                        return this.restore(this.index);                    }                }                this.restore(++this.index);            }        };        this.restore = function () {            var me = this.editor;            var scene = this.list[this.index];            var root = UE.htmlparser(scene.content.replace(fillchar, ''));            me.options.autoClearEmptyNode = false;            me.filterInputRule(root);            me.options.autoClearEmptyNode = orgState;            //trace:873            //去掉展位符            me.document.body.innerHTML = root.toHtml();            me.fireEvent('afterscencerestore');            //处理undo后空格不展位的问题            if (browser.ie) {                utils.each(domUtils.getElementsByTagName(me.document,'td th caption p'),function(node){                    if(domUtils.isEmptyNode(node)){                        domUtils.fillNode(me.document, node);                    }                })            }            try{                var rng = new dom.Range(me.document).moveToAddress(scene.address);                rng.select(noNeedFillCharTags[rng.startContainer.nodeName.toLowerCase()]);            }catch(e){}            this.update();            this.clearKey();            //不能把自己reset了            me.fireEvent('reset', true);        };        this.getScene = function () {            var me = this.editor;            var rng = me.selection.getRange(),                rngAddress = rng.createAddress(false,true);            me.fireEvent('beforegetscene');            var root = UE.htmlparser(me.body.innerHTML);            me.options.autoClearEmptyNode = false;            me.filterOutputRule(root);            me.options.autoClearEmptyNode = orgState;            var cont = root.toHtml();            //trace:3461            //这个会引起回退时导致空格丢失的情况//            browser.ie && (cont = cont.replace(/> </g, '><').replace(/\s*</g, '<').replace(/>\s*/g, '>'));            me.fireEvent('aftergetscene');            return {                address:rngAddress,                content:cont            }        };        this.save = function (notCompareRange,notSetCursor) {            clearTimeout(saveSceneTimer);            var currentScene = this.getScene(notSetCursor),                lastScene = this.list[this.index];            if(lastScene && lastScene.content != currentScene.content){                me.trigger('contentchange')            }            //内容相同位置相同不存            if (lastScene && lastScene.content == currentScene.content &&                ( notCompareRange ? 1 : compareRangeAddress(lastScene.address, currentScene.address) )                ) {                return;            }            this.list = this.list.slice(0, this.index + 1);            this.list.push(currentScene);            //如果大于最大数量了,就把最前的剔除            if (this.list.length > maxUndoCount) {                this.list.shift();            }            this.index = this.list.length - 1;            this.clearKey();            //跟新undo/redo状态            this.update();        };        this.update = function () {            this.hasRedo = !!this.list[this.index + 1];            this.hasUndo = !!this.list[this.index - 1];        };        this.reset = function () {            this.list = [];            this.index = 0;            this.hasUndo = false;            this.hasRedo = false;            this.clearKey();        };        this.clearKey = function () {            keycont = 0;            lastKeyCode = null;        };    }    me.undoManger = new UndoManager();    me.undoManger.editor = me;    function saveScene() {        this.undoManger.save();    }    me.addListener('saveScene', function () {        var args = Array.prototype.splice.call(arguments,1);        this.undoManger.save.apply(this.undoManger,args);    });//    me.addListener('beforeexeccommand', saveScene);//    me.addListener('afterexeccommand', saveScene);    me.addListener('reset', function (type, exclude) {        if (!exclude) {            this.undoManger.reset();        }    });    me.commands['redo'] = me.commands['undo'] = {        execCommand:function (cmdName) {            this.undoManger[cmdName]();        },        queryCommandState:function (cmdName) {            return this.undoManger['has' + (cmdName.toLowerCase() == 'undo' ? 'Undo' : 'Redo')] ? 0 : -1;        },        notNeedUndo:1    };    var keys = {            //  /*Backspace*/ 8:1, /*Delete*/ 46:1,            /*Shift*/ 16:1, /*Ctrl*/ 17:1, /*Alt*/ 18:1,            37:1, 38:1, 39:1, 40:1        },        keycont = 0,        lastKeyCode;    //输入法状态下不计算字符数    var inputType = false;    me.addListener('ready', function () {        domUtils.on(this.body, 'compositionstart', function () {            inputType = true;        });        domUtils.on(this.body, 'compositionend', function () {            inputType = false;        })    });    //快捷键    me.addshortcutkey({        "Undo":"ctrl+90", //undo        "Redo":"ctrl+89" //redo    });    var isCollapsed = true;    me.addListener('keydown', function (type, evt) {        var me = this;        var keyCode = evt.keyCode || evt.which;        if (!keys[keyCode] && !evt.ctrlKey && !evt.metaKey && !evt.shiftKey && !evt.altKey) {            if (inputType)                return;            if(!me.selection.getRange().collapsed){                me.undoManger.save(false,true);                isCollapsed = false;                return;            }            if (me.undoManger.list.length == 0) {                me.undoManger.save(true);            }            clearTimeout(saveSceneTimer);            function save(cont){                cont.undoManger.save(false,true);                cont.fireEvent('selectionchange');            }            saveSceneTimer = setTimeout(function(){                if(inputType){                    var interalTimer = setInterval(function(){                        if(!inputType){                            save(me);                            clearInterval(interalTimer)                        }                    },300)                    return;                }                save(me);            },200);            lastKeyCode = keyCode;            keycont++;            if (keycont >= maxInputCount ) {                save(me)            }        }    });    me.addListener('keyup', function (type, evt) {        var keyCode = evt.keyCode || evt.which;        if (!keys[keyCode] && !evt.ctrlKey && !evt.metaKey && !evt.shiftKey && !evt.altKey) {            if (inputType)                return;            if(!isCollapsed){                this.undoManger.save(false,true);                isCollapsed = true;            }        }    });    //扩展实例,添加关闭和开启命令undo    me.stopCmdUndo = function(){        me.__hasEnterExecCommand = true;    };    me.startCmdUndo = function(){        me.__hasEnterExecCommand = false;    }};
 |