AutorÃa | Ultima modificación | Ver Log |
YUI.add('moodle-atto_undo-button', function (Y, NAME) {// This file is part of Moodle - http://moodle.org///// Moodle is free software: you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation, either version 3 of the License, or// (at your option) any later version.//// Moodle is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with Moodle. If not, see <http://www.gnu.org/licenses/>./*** @component atto_undo* @copyright 2014 Jerome Mouneyrac* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later*//*** @module moodle-atto_undo-button*//*** Atto text editor undo plugin.** @namespace M.atto_undo* @class button* @extends M.editor_atto.EditorPlugin*/Y.namespace('M.atto_undo').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], {/*** The maximum saved number of undo steps.** @property _maxUndos* @type {Number} The maximum number of saved undos.* @default 40* @private*/_maxUndos: 40,/*** History of edits.** @property _undoStack* @type {Array} The elements of the array are the html strings that make a snapshot* @private*/_undoStack: null,/*** History of edits.** @property _redoStack* @type {Array} The elements of the array are the html strings that make a snapshot* @private*/_redoStack: null,/*** Add the buttons to the toolbar** @method initializer*/initializer: function() {// Initialise the undo and redo stacks.this._undoStack = [];this._redoStack = [];this.addButton({title: 'undo',icon: 'e/undo',callback: this._undoHandler,buttonName: 'undo',keys: 90});this.addButton({title: 'redo',icon: 'e/redo',callback: this._redoHandler,buttonName: 'redo',keys: 89});// Enable the undo once everything has loaded.this.get('host').on('pluginsloaded', function() {// Adds the current value to the stack.this._addToUndo(this._getHTML());this.get('host').on('atto:selectionchanged', this._changeListener, this);}, this);this._updateButtonsStates();},/*** Adds an element to the redo stack.** @method _addToRedo* @private* @param {String} html The HTML content to save.*/_addToRedo: function(html) {this._redoStack.push(html);},/*** Adds an element to the undo stack.** @method _addToUndo* @private* @param {String} html The HTML content to save.* @param {Boolean} [clearRedo=false] Whether or not we should clear the redo stack.*/_addToUndo: function(html, clearRedo) {var last = this._undoStack[this._undoStack.length - 1];if (typeof clearRedo === 'undefined') {clearRedo = false;}if (last !== html) {this._undoStack.push(html);if (clearRedo) {this._redoStack = [];}}while (this._undoStack.length > this._maxUndos) {this._undoStack.shift();}},/*** Get the editor HTML.** @method _getHTML* @private* @return {String} The HTML.*/_getHTML: function() {return this.get('host').getCleanHTML();},/*** Get an element on the redo stack.** @method _getRedo* @private* @return {String} The HTML to restore, or undefined.*/_getRedo: function() {return this._redoStack.pop();},/*** Get an element on the undo stack.** @method _getUndo* @private* @param {String} current The current HTML.* @return {String} The HTML to restore.*/_getUndo: function(current) {if (this._undoStack.length === 1) {return this._undoStack[0];}var last = this._undoStack.pop();if (last === current) {// Oops, the latest undo step is the current content, we should unstack once more.// There is no need to do that in a loop as the same stack should never contain duplicates.last = this._undoStack.pop();}// We always need to keep the first element of the stack.if (this._undoStack.length === 0) {this._addToUndo(last);}return last;},/*** Restore a value from a stack.** @method _restoreValue* @private* @param {String} html The HTML to restore in the editor.*/_restoreValue: function(html) {this.editor.setHTML(html);// We always add the restored value to the stack, otherwise an event could think that// the content has changed and clear the redo stack.this._addToUndo(html);},/*** Update the states of the buttons.** @method _updateButtonsStates* @private*/_updateButtonsStates: function() {if (this._undoStack.length > 1) {this.enableButtons('undo');} else {this.disableButtons('undo');}if (this._redoStack.length > 0) {this.enableButtons('redo');} else {this.disableButtons('redo');}},/*** Handle a click on undo** @method _undoHandler* @param {Event} The click event* @private*/_undoHandler: function(e) {e.preventDefault();var html = this._getHTML(),undo = this._getUndo(html);// Edge case, but that could happen. We do nothing when the content equals the undo step.if (html === undo) {this._updateButtonsStates();return;}// Restore the value.this._restoreValue(undo);// Add to the redo stack.this._addToRedo(html);// Update the button states.this._updateButtonsStates();},/*** Handle a click on redo** @method _redoHandler* @param {Event} The click event* @private*/_redoHandler: function(e) {e.preventDefault();// Don't do anything if redo stack is empty.if (this._redoStack.length === 0) {return;}var html = this._getHTML(),redo = this._getRedo();// Edge case, but that could happen. We do nothing when the content equals the redo step.if (html === redo) {this._updateButtonsStates();return;}// Restore the value.this._restoreValue(redo);// Update the button states.this._updateButtonsStates();},/*** If we are significantly different from the last saved version, save a new version.** @method _changeListener* @param {EventFacade} The click event* @private*/_changeListener: function(e) {if (e.event && e.event.type.indexOf('key') !== -1) {// These are the 4 arrow keys.if ((e.event.keyCode !== 39) &&(e.event.keyCode !== 37) &&(e.event.keyCode !== 40) &&(e.event.keyCode !== 38)) {// Skip this event type. We only want focus/mouse/arrow events.return;}}this._addToUndo(this._getHTML(), true);this._updateButtonsStates();}});}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]});