|
98 | 98 | });
|
99 | 99 | }
|
100 | 100 |
|
| 101 | + /** |
| 102 | + * Reset undo stack. |
| 103 | + * |
| 104 | + * @member CKEDITOR.editor |
| 105 | + */ |
101 | 106 | editor.resetUndo = function() {
|
102 | 107 | // Reset the undo stack.
|
103 | 108 | undoManager.reset();
|
|
124 | 129 | if ( undoManager.currentImage )
|
125 | 130 | undoManager.update();
|
126 | 131 | });
|
| 132 | + |
| 133 | + /** |
| 134 | + * Lock manager to prevent any save/update operations. |
| 135 | + * |
| 136 | + * It's convenient to lock manager before doing DOM operations |
| 137 | + * that shouldn't be recored (e.g. auto paragraphing). |
| 138 | + * |
| 139 | + * See {@link CKEDITOR.plugins.undo.UndoManager#lock} for more details. |
| 140 | + * |
| 141 | + * @event lockSnapshot |
| 142 | + * @member CKEDITOR.editor |
| 143 | + */ |
| 144 | + editor.on( 'lockSnapshot', undoManager.lock, undoManager ); |
| 145 | + |
| 146 | + /** |
| 147 | + * Unlock manager and update latest snapshot. |
| 148 | + * |
| 149 | + * @event unlockSnapshot |
| 150 | + * @member CKEDITOR.editor |
| 151 | + */ |
| 152 | + editor.on( 'unlockSnapshot', undoManager.unlock, undoManager ); |
127 | 153 | }
|
128 | 154 | });
|
129 | 155 |
|
|
218 | 244 | navigationKeyCodes = { 37:1,38:1,39:1,40:1 }; // Arrows: L, T, R, B
|
219 | 245 |
|
220 | 246 | UndoManager.prototype = {
|
| 247 | + /** |
| 248 | + * When `locked` property is not `null` manager is locked, so |
| 249 | + * operations like `save` or `update` are forbidden. |
| 250 | + * |
| 251 | + * Manager can be locked/unlocked by {@link #lock} and {@link #unlock} methods. |
| 252 | + * |
| 253 | + * @private |
| 254 | + * @property {Object} [locked=null] |
| 255 | + */ |
| 256 | + |
221 | 257 | /**
|
222 | 258 | * Process undo system regard keystrikes.
|
223 | 259 | * @param {CKEDITOR.dom.event} event
|
|
322 | 358 |
|
323 | 359 | this.hasUndo = false;
|
324 | 360 | this.hasRedo = false;
|
325 |
| - |
326 |
| - // Finish transaction. |
327 |
| - this.isLocked = false; |
| 361 | + this.locked = null; |
328 | 362 |
|
329 | 363 | this.resetType();
|
330 | 364 | },
|
|
354 | 388 | */
|
355 | 389 | save: function( onContentOnly, image, autoFireChange ) {
|
356 | 390 | // Do not change snapshots stack when locked.
|
357 |
| - if ( this.isLocked ) |
| 391 | + if ( this.locked ) |
358 | 392 | return false;
|
359 | 393 |
|
360 | 394 | var snapshots = this.snapshots;
|
|
402 | 436 | // Start transaction - do not allow any mutations to the
|
403 | 437 | // snapshots stack done when selecting bookmarks (much probably
|
404 | 438 | // by selectionChange listener).
|
405 |
| - this.isLocked = true; |
| 439 | + this.locked = 1; |
406 | 440 |
|
407 | 441 | this.editor.loadSnapshot( image.contents );
|
408 | 442 |
|
|
417 | 451 | $range.select();
|
418 | 452 | }
|
419 | 453 |
|
420 |
| - this.isLocked = false; |
| 454 | + this.locked = 0; |
421 | 455 |
|
422 | 456 | this.index = image.index;
|
423 | 457 |
|
|
514 | 548 | * Update the last snapshot of the undo stack with the current editor content.
|
515 | 549 | */
|
516 | 550 | update: function() {
|
517 |
| - // Do not change snapshots stack when locked. |
518 |
| - if ( !this.isLocked ) |
| 551 | + // Do not change snapshots stack is locked. |
| 552 | + if ( !this.locked ) |
519 | 553 | this.snapshots.splice( this.index, 1, ( this.currentImage = new Image( this.editor ) ) );
|
| 554 | + }, |
| 555 | + |
| 556 | + /** |
| 557 | + * Lock the snapshot stack to prevent any save/update operations, and additionally |
| 558 | + * update the tip snapshot with the DOM changes during the locked period when necessary, |
| 559 | + * after the {@link #unlock} method is called. |
| 560 | + * |
| 561 | + * It's mainly used for ensure any DOM operations that shouldn't be recorded (e.g. auto paragraphing). |
| 562 | + */ |
| 563 | + lock: function() { |
| 564 | + if ( !this.locked ) { |
| 565 | + var snapBefore = this.editor.getSnapshot(); |
| 566 | + |
| 567 | + // If current editor content matches the tip of snapshot stack, |
| 568 | + // the stack tip must be updated by unlock, to include any changes made |
| 569 | + // during this period. |
| 570 | + var matchedTip = this.currentImage && snapBefore == this.currentImage.contents; |
| 571 | + |
| 572 | + this.locked = { update: matchedTip ? snapBefore : null }; |
| 573 | + } |
| 574 | + }, |
| 575 | + |
| 576 | + /** |
| 577 | + * Unlock the snapshot stack and check to amend the last snapshot. |
| 578 | + * |
| 579 | + * See {@link #lock} for more details. |
| 580 | + */ |
| 581 | + unlock: function() { |
| 582 | + if ( this.locked ) { |
| 583 | + var update = this.locked.update, |
| 584 | + snap = this.editor.getSnapshot(); |
| 585 | + |
| 586 | + this.locked = null; |
| 587 | + |
| 588 | + if ( typeof update == 'string' && snap != update ) |
| 589 | + this.update(); |
| 590 | + } |
520 | 591 | }
|
521 | 592 | };
|
522 | 593 | })();
|
|
0 commit comments