[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/editor/atto/plugins/undo/yui/build/moodle-atto_undo-button/ -> moodle-atto_undo-button-debug.js (source)

   1  YUI.add('moodle-atto_undo-button', function (Y, NAME) {
   2  
   3  // This file is part of Moodle - http://moodle.org/
   4  //
   5  // Moodle is free software: you can redistribute it and/or modify
   6  // it under the terms of the GNU General Public License as published by
   7  // the Free Software Foundation, either version 3 of the License, or
   8  // (at your option) any later version.
   9  //
  10  // Moodle is distributed in the hope that it will be useful,
  11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13  // GNU General Public License for more details.
  14  //
  15  // You should have received a copy of the GNU General Public License
  16  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  17  
  18  /**
  19   * @component  atto_undo
  20   * @copyright  2014 Jerome Mouneyrac
  21   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  22   */
  23  
  24  /**
  25   * @module moodle-atto_undo-button
  26   */
  27  
  28  /**
  29   * Atto text editor undo plugin.
  30   *
  31   * @namespace M.atto_undo
  32   * @class button
  33   * @extends M.editor_atto.EditorPlugin
  34   */
  35  
  36  Y.namespace('M.atto_undo').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], {
  37      /**
  38       * The maximum saved number of undo steps.
  39       *
  40       * @property _maxUndos
  41       * @type {Number} The maximum number of saved undos.
  42       * @default 40
  43       * @private
  44       */
  45      _maxUndos: 40,
  46  
  47      /**
  48       * History of edits.
  49       *
  50       * @property _undoStack
  51       * @type {Array} The elements of the array are the html strings that make a snapshot
  52       * @private
  53       */
  54      _undoStack: null,
  55  
  56      /**
  57       * History of edits.
  58       *
  59       * @property _redoStack
  60       * @type {Array} The elements of the array are the html strings that make a snapshot
  61       * @private
  62       */
  63      _redoStack: null,
  64  
  65      /**
  66       * Add the buttons to the toolbar
  67       *
  68       * @method initializer
  69       */
  70      initializer: function() {
  71          // Initialise the undo and redo stacks.
  72          this._undoStack = [];
  73          this._redoStack = [];
  74  
  75          this.addButton({
  76              title: 'undo',
  77              icon: 'e/undo',
  78              callback: this._undoHandler,
  79              buttonName: 'undo',
  80              keys: 90
  81          });
  82  
  83          this.addButton({
  84              title: 'redo',
  85              icon: 'e/redo',
  86              callback: this._redoHandler,
  87              buttonName: 'redo',
  88              keys: 89
  89          });
  90  
  91          // Enable the undo once everything has loaded.
  92          this.get('host').on('pluginsloaded', function() {
  93              // Adds the current value to the stack.
  94              this._addToUndo(this._getHTML());
  95              this.get('host').on('atto:selectionchanged', this._changeListener, this);
  96          }, this);
  97  
  98          this._updateButtonsStates();
  99      },
 100  
 101      /**
 102       * Adds an element to the redo stack.
 103       *
 104       * @method _addToRedo
 105       * @private
 106       * @param {String} html The HTML content to save.
 107       */
 108      _addToRedo: function(html) {
 109          this._redoStack.push(html);
 110      },
 111  
 112      /**
 113       * Adds an element to the undo stack.
 114       *
 115       * @method _addToUndo
 116       * @private
 117       * @param {String} html The HTML content to save.
 118       * @param {Boolean} [clearRedo=false] Whether or not we should clear the redo stack.
 119       */
 120      _addToUndo: function(html, clearRedo) {
 121          var last = this._undoStack[this._undoStack.length - 1];
 122  
 123          if (typeof clearRedo === 'undefined') {
 124              clearRedo = false;
 125          }
 126  
 127          if (last !== html) {
 128              this._undoStack.push(html);
 129              if (clearRedo) {
 130                  this._redoStack = [];
 131              }
 132          }
 133  
 134          while (this._undoStack.length > this._maxUndos) {
 135              this._undoStack.shift();
 136          }
 137      },
 138  
 139      /**
 140       * Get the editor HTML.
 141       *
 142       * @method _getHTML
 143       * @private
 144       * @return {String} The HTML.
 145       */
 146      _getHTML: function() {
 147          return this.get('host').getCleanHTML();
 148      },
 149  
 150      /**
 151       * Get an element on the redo stack.
 152       *
 153       * @method _getRedo
 154       * @private
 155       * @return {String} The HTML to restore, or undefined.
 156       */
 157      _getRedo: function() {
 158          return this._redoStack.pop();
 159      },
 160  
 161      /**
 162       * Get an element on the undo stack.
 163       *
 164       * @method _getUndo
 165       * @private
 166       * @param {String} current The current HTML.
 167       * @return {String} The HTML to restore.
 168       */
 169      _getUndo: function(current) {
 170          if (this._undoStack.length === 1) {
 171              return this._undoStack[0];
 172          }
 173  
 174          var last = this._undoStack.pop();
 175          if (last === current) {
 176              // Oops, the latest undo step is the current content, we should unstack once more.
 177              // There is no need to do that in a loop as the same stack should never contain duplicates.
 178              last = this._undoStack.pop();
 179          }
 180  
 181          // We always need to keep the first element of the stack.
 182          if (this._undoStack.length === 0) {
 183              this._addToUndo(last);
 184          }
 185  
 186          return last;
 187      },
 188  
 189      /**
 190       * Restore a value from a stack.
 191       *
 192       * @method _restoreValue
 193       * @private
 194       * @param {String} html The HTML to restore in the editor.
 195       */
 196      _restoreValue: function(html) {
 197          this.editor.setHTML(html);
 198          // We always add the restored value to the stack, otherwise an event could think that
 199          // the content has changed and clear the redo stack.
 200          this._addToUndo(html);
 201      },
 202  
 203      /**
 204       * Update the states of the buttons.
 205       *
 206       * @method _updateButtonsStates
 207       * @private
 208       */
 209      _updateButtonsStates: function() {
 210          if (this._undoStack.length > 1) {
 211              this.enableButtons('undo');
 212          } else {
 213              this.disableButtons('undo');
 214          }
 215  
 216          if (this._redoStack.length > 0) {
 217              this.enableButtons('redo');
 218          } else {
 219              this.disableButtons('redo');
 220          }
 221      },
 222  
 223      /**
 224       * Handle a click on undo
 225       *
 226       * @method _undoHandler
 227       * @param {Event} The click event
 228       * @private
 229       */
 230      _undoHandler: function(e) {
 231          e.preventDefault();
 232          var html = this._getHTML(),
 233              undo = this._getUndo(html);
 234  
 235          // Edge case, but that could happen. We do nothing when the content equals the undo step.
 236          if (html === undo) {
 237              this._updateButtonsStates();
 238              return;
 239          }
 240  
 241          // Restore the value.
 242          this._restoreValue(undo);
 243  
 244          // Add to the redo stack.
 245          this._addToRedo(html);
 246  
 247          // Update the button states.
 248          this._updateButtonsStates();
 249      },
 250  
 251      /**
 252       * Handle a click on redo
 253       *
 254       * @method _redoHandler
 255       * @param {Event} The click event
 256       * @private
 257       */
 258      _redoHandler: function(e) {
 259          e.preventDefault();
 260          var html = this._getHTML(),
 261              redo = this._getRedo();
 262  
 263          // Edge case, but that could happen. We do nothing when the content equals the redo step.
 264          if (html === redo) {
 265              this._updateButtonsStates();
 266              return;
 267          }
 268          // Restore the value.
 269          this._restoreValue(redo);
 270  
 271          // Update the button states.
 272          this._updateButtonsStates();
 273      },
 274  
 275      /**
 276       * If we are significantly different from the last saved version, save a new version.
 277       *
 278       * @method _changeListener
 279       * @param {EventFacade} The click event
 280       * @private
 281       */
 282      _changeListener: function(e) {
 283          if (e.event && e.event.type.indexOf('key') !== -1) {
 284              // These are the 4 arrow keys.
 285              if ((e.event.keyCode !== 39) &&
 286                      (e.event.keyCode !== 37) &&
 287                      (e.event.keyCode !== 40) &&
 288                      (e.event.keyCode !== 38)) {
 289                  // Skip this event type. We only want focus/mouse/arrow events.
 290                  return;
 291              }
 292          }
 293  
 294          this._addToUndo(this._getHTML(), true);
 295          this._updateButtonsStates();
 296      }
 297  });
 298  
 299  
 300  }, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]});


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1