all files / editor-manager/plugin/ undo.js

97.6% Statements 163/167
92.68% Branches 76/82
100% Functions 19/19
97.6% Lines 163/167
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250   2619× 2619× 2619× 2619× 2619×   2619× 2619× 2619× 2619× 2619× 2619×   11× 11×           2448× 2448× 2448× 2448× 2448× 2448×   41× 27×     14×     2448× 2448× 2448× 2448× 2448× 2448×   626× 626× 626×   16× 16× 16×       93× 88×     1611× 1611× 2064× 2064× 655×   1409× 1409×     1611×   97×     97× 134× 134× 134×     134×     134× 45×     52×   2950× 99×   2851× 2851×   2851× 2372×     15×     2851× 2851× 2851× 2851× 2851× 6839×   2851× 2851× 1407×   2851×             52×   2799× 2799× 2799× 33× 33×   2799× 12×     2851× 2851× 23×   2851× 2851× 38×   2851× 2851× 68×   2851× 2851× 394× 394×   2851× 2851× 25×   2851× 2851× 546× 546×   2851×   43× 43× 43× 43× 43× 43× 43× 43×   43× 43× 43× 24×                   19× 18× 18× 18× 18× 18× 18× 18×     18× 18× 18× 13×                   11326× 11326× 4679×   11326× 89×   11326×   849×          
define(["require", "exports", "@syncfusion/ej2-base", "./../../selection/selection", "./../../common/constant", "../../common/util", "./../../common/constant"], function (require, exports, ej2_base_1, selection_1, EVENTS, util_1, constant_1) {
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    var UndoRedoManager = (function () {
        function UndoRedoManager(parent, options) {
            this.undoRedoStack = [];
            this.parent = parent;
            this.undoRedoSteps = !ej2_base_1.isNullOrUndefined(options) ? options.undoRedoSteps : 30;
            this.undoRedoTimer = !ej2_base_1.isNullOrUndefined(options) ? options.undoRedoTimer : 300;
            this.addEventListener();
        }
        UndoRedoManager.prototype.addEventListener = function () {
            this.debounceListener = ej2_base_1.debounce(this.keyUp, this.undoRedoTimer);
            this.parent.observer.on(EVENTS.KEY_UP_HANDLER, this.debounceListener, this);
            this.parent.observer.on(EVENTS.KEY_DOWN_HANDLER, this.keyDown, this);
            this.parent.observer.on(EVENTS.ACTION, this.onAction, this);
            this.parent.observer.on(EVENTS.MODEL_CHANGED_PLUGIN, this.onPropertyChanged, this);
            this.parent.observer.on(EVENTS.INTERNAL_DESTROY, this.destroy, this);
        };
        UndoRedoManager.prototype.onPropertyChanged = function (props) {
            for (var _i = 0, _a = Object.keys(props.newProp); _i < _a.length; _i++) {
                var prop = _a[_i];
                switch (prop) {
                    case 'undoRedoSteps':
                        this.undoRedoSteps = props.newProp.undoRedoSteps;
                        break;
                    case 'undoRedoTimer':
                        this.undoRedoTimer = props.newProp.undoRedoTimer;
                        break;
                }
            }
        };
        UndoRedoManager.prototype.removeEventListener = function () {
            this.parent.observer.off(EVENTS.KEY_UP_HANDLER, this.keyUp);
            this.parent.observer.off(EVENTS.KEY_DOWN_HANDLER, this.keyDown);
            this.parent.observer.off(EVENTS.ACTION, this.onAction);
            this.parent.observer.off(EVENTS.MODEL_CHANGED_PLUGIN, this.onPropertyChanged);
            this.parent.observer.off(EVENTS.INTERNAL_DESTROY, this.destroy);
            this.debounceListener = null;
        };
        UndoRedoManager.prototype.onAction = function (e) {
            if (e.subCommand === 'Undo') {
                this.undo(e);
            }
            else {
                this.redo(e);
            }
        };
        UndoRedoManager.prototype.destroy = function () {
            this.removeEventListener();
            this.element = null;
            this.steps = null;
            this.undoRedoStack = [];
            this.undoRedoSteps = null;
            this.undoRedoTimer = null;
        };
        UndoRedoManager.prototype.keyDown = function (e) {
            var event = e.event;
            var proxy = this;
            switch (event.action) {
                case 'undo':
                    event.preventDefault();
                    proxy.undo(e);
                    break;
                case 'redo':
                    event.preventDefault();
                    proxy.redo(e);
                    break;
            }
        };
        UndoRedoManager.prototype.keyUp = function (e) {
            if (e.event.keyCode !== 17 && !e.event.ctrlKey) {
                this.saveData(e);
            }
        };
        UndoRedoManager.prototype.getTextContentFromFragment = function (fragment) {
            var textContent = '';
            for (var i = 0; i < fragment.childNodes.length; i++) {
                var childNode = fragment.childNodes[i];
                if (childNode.nodeType === Node.TEXT_NODE) {
                    textContent += childNode.textContent;
                }
                else Eif (childNode.nodeType === Node.ELEMENT_NODE) {
                    textContent += this.getTextContentFromFragment(childNode);
                }
            }
            return textContent;
        };
        UndoRedoManager.prototype.isElementStructureEqual = function (previousFragment, currentFragment) {
            Iif (previousFragment.childNodes.length !== currentFragment.childNodes.length) {
                return false;
            }
            for (var i = 0; i < previousFragment.childNodes.length; i++) {
                var previousFragmentNode = previousFragment.childNodes[i];
                var currentFragmentNode = currentFragment.childNodes[i];
                Iif (!previousFragmentNode || !currentFragmentNode) {
                    return false;
                }
                Iif (previousFragmentNode.nodeType !== currentFragmentNode.nodeType) {
                    return false;
                }
                if (previousFragmentNode.outerHTML !== currentFragmentNode.outerHTML) {
                    return false;
                }
            }
            return true;
        };
        UndoRedoManager.prototype.saveData = function (e) {
            if (!this.parent.currentDocument) {
                return;
            }
            var range = new selection_1.NodeSelection(this.parent.editableElement).getRange(this.parent.currentDocument);
            var currentContainer = this.parent.editableElement === range.startContainer.parentElement ?
                range.startContainer.parentElement : range.startContainer;
            for (var i = currentContainer.childNodes.length - 1; i >= 0; i--) {
                if (!ej2_base_1.isNullOrUndefined(currentContainer.childNodes[i]) && currentContainer.childNodes[i].nodeName === '#text' &&
                    currentContainer.childNodes[i].textContent.length === 0 && currentContainer.childNodes[i].nodeName !== 'IMG' &&
                    currentContainer.childNodes[i].nodeName !== 'BR' && currentContainer.childNodes[i].nodeName && 'HR') {
                    ej2_base_1.detach(currentContainer.childNodes[i]);
                }
            }
            range = new selection_1.NodeSelection(this.parent.editableElement).getRange(this.parent.currentDocument);
            var save = new selection_1.NodeSelection(this.parent.editableElement).save(range, this.parent.currentDocument);
            var clonedElement = this.removeResizeElement(this.parent.editableElement.cloneNode(true));
            var fragment = document.createDocumentFragment();
            while (clonedElement.firstChild) {
                fragment.appendChild(clonedElement.firstChild);
            }
            var changEle = { text: fragment, range: save };
            if (this.undoRedoStack.length >= this.steps) {
                this.undoRedoStack = this.undoRedoStack.slice(0, this.steps + 1);
            }
            if (this.undoRedoStack.length > 1 && (this.undoRedoStack[this.undoRedoStack.length - 1].range.range.collapsed === range.collapsed)
                && (this.undoRedoStack[this.undoRedoStack.length - 1].range.startOffset === save.range.startOffset) &&
                (this.undoRedoStack[this.undoRedoStack.length - 1].range.endOffset === save.range.endOffset) &&
                (this.undoRedoStack[this.undoRedoStack.length - 1].range.range.startContainer === save.range.startContainer) &&
                (this.getTextContentFromFragment(this.undoRedoStack[this.undoRedoStack.length - 1].text).trim() ===
                    this.getTextContentFromFragment(changEle.text).trim()) &&
                this.isElementStructureEqual(this.undoRedoStack[this.undoRedoStack.length - 1].text, changEle.text)) {
                return;
            }
            this.undoRedoStack.push(changEle);
            this.steps = this.undoRedoStack.length - 1;
            if (this.steps > this.undoRedoSteps) {
                this.undoRedoStack.shift();
                this.steps--;
            }
            if (e && e.callBack) {
                e.callBack();
            }
        };
        UndoRedoManager.prototype.removeResizeElement = function (element) {
            var videoResize = element.querySelector('.e-vid-resize');
            if (videoResize) {
                ej2_base_1.detach(videoResize);
            }
            var videoFocus = element.querySelector("." + constant_1.CLS_VID_FOCUS);
            if (videoFocus) {
                ej2_base_1.removeClass([videoFocus], [constant_1.CLS_VID_FOCUS, 'e-resize']);
            }
            var imageResize = element.querySelector('.e-img-resize');
            if (imageResize) {
                ej2_base_1.detach(imageResize);
            }
            var images = element.querySelectorAll('img');
            for (var i = 0; i < images.length; i++) {
                var img = images[i];
                ej2_base_1.removeClass([img], ['e-img-focus', 'e-resize']);
            }
            var audioFocus = element.querySelector("." + constant_1.CLS_AUD_FOCUS);
            if (audioFocus) {
                ej2_base_1.removeClass([audioFocus], [constant_1.CLS_AUD_FOCUS]);
            }
            var outlineElements = element.querySelectorAll('img, audio, video');
            for (var i = 0; i < outlineElements.length; i++) {
                var outlineElem = outlineElements[i];
                outlineElem.style.outline = '';
            }
            return element;
        };
        UndoRedoManager.prototype.undo = function (e) {
            Eif (this.steps > 0) {
                var range = this.undoRedoStack[this.steps - 1].range;
                var removedContent = this.undoRedoStack[this.steps - 1].text;
                this.parent.editableElement.innerHTML = '';
                this.parent.editableElement.appendChild(removedContent.cloneNode(true));
                this.parent.editableElement.focus();
                util_1.scrollToCursor(this.parent.currentDocument, this.parent.editableElement);
                if (util_1.isIDevice()) {
                    util_1.setEditFrameFocus(this.parent.editableElement, e.selector);
                }
                range.restore();
                this.steps--;
                if (e.callBack) {
                    e.callBack({
                        requestType: 'Undo',
                        editorMode: 'HTML',
                        range: range,
                        elements: this.parent.nodeSelection.getSelectedNodes(this.parent.currentDocument),
                        event: e.event
                    });
                }
            }
        };
        UndoRedoManager.prototype.redo = function (e) {
            if (this.undoRedoStack[this.steps + 1] != null) {
                var range = this.undoRedoStack[this.steps + 1].range;
                var addedContent = this.undoRedoStack[this.steps + 1].text;
                this.parent.editableElement.innerHTML = '';
                this.parent.editableElement.appendChild(addedContent.cloneNode(true));
                this.parent.editableElement.focus();
                util_1.scrollToCursor(this.parent.currentDocument, this.parent.editableElement);
                Iif (util_1.isIDevice()) {
                    util_1.setEditFrameFocus(this.parent.editableElement, e.selector);
                }
                range.restore();
                this.steps++;
                if (e.callBack) {
                    e.callBack({
                        requestType: 'Redo',
                        editorMode: 'HTML',
                        range: range,
                        elements: this.parent.nodeSelection.getSelectedNodes(this.parent.currentDocument),
                        event: e.event
                    });
                }
            }
        };
        UndoRedoManager.prototype.getUndoStatus = function () {
            var status = { undo: false, redo: false };
            if (this.steps > 0) {
                status.undo = true;
            }
            if (this.undoRedoStack[this.steps + 1] != null) {
                status.redo = true;
            }
            return status;
        };
        UndoRedoManager.prototype.getCurrentStackIndex = function () {
            return this.steps;
        };
        UndoRedoManager.prototype.clear = function () {
            this.undoRedoStack = [];
            this.steps = null;
        };
        return UndoRedoManager;
    }());
    exports.UndoRedoManager = UndoRedoManager;
});