/*\r
-Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.\r
+Copyright (c) 2003-2013, CKSource - Frederico Knabben. All rights reserved.\r
For licensing, see LICENSE.html or http://ckeditor.com/license\r
*/\r
\r
editor.on( 'afterCommandExec', recordCommand );\r
\r
// Save snapshots before doing custom changes.\r
- editor.on( 'saveSnapshot', function()\r
+ editor.on( 'saveSnapshot', function( evt )\r
{\r
- undoManager.save();\r
+ undoManager.save( evt.data && evt.data.contentOnly );\r
});\r
\r
// Registering keydown on every document recreation.(#3844)\r
// Make the undo manager available only in wysiwyg mode.\r
editor.on( 'mode', function()\r
{\r
- undoManager.enabled = editor.mode == 'wysiwyg';\r
+ undoManager.enabled = editor.readOnly ? false : editor.mode == 'wysiwyg';\r
undoManager.onChange();\r
});\r
\r
// Create the first image.\r
editor.fire( 'saveSnapshot' );\r
};\r
+\r
+ /**\r
+ * Amend the top of undo stack (last undo image) with the current DOM changes.\r
+ * @name CKEDITOR.editor#updateUndo\r
+ * @example\r
+ * function()\r
+ * {\r
+ * editor.fire( 'saveSnapshot' );\r
+ * editor.document.body.append(...);\r
+ * // Make new changes following the last undo snapshot part of it.\r
+ * editor.fire( 'updateSnapshot' );\r
+ * ...\r
+ * }\r
+ */\r
+ editor.on( 'updateSnapshot', function()\r
+ {\r
+ if ( undoManager.currentImage )\r
+ undoManager.update();\r
+ });\r
}\r
});\r
\r
- // Gets a snapshot image which represent the current document status.\r
- function Image( editor )\r
+ CKEDITOR.plugins.undo = {};\r
+\r
+ /**\r
+ * Undo snapshot which represents the current document status.\r
+ * @name CKEDITOR.plugins.undo.Image\r
+ * @param editor The editor instance on which the image is created.\r
+ */\r
+ var Image = CKEDITOR.plugins.undo.Image = function( editor )\r
{\r
- var contents = editor.getSnapshot(),\r
+ this.editor = editor;\r
+\r
+ editor.fire( 'beforeUndoImage' );\r
+\r
+ var contents = editor.getSnapshot(),\r
selection = contents && editor.getSelection();\r
\r
// In IE, we need to remove the expando attributes.\r
- CKEDITOR.env.ie && contents && ( contents = contents.replace( /\s+_cke_expando=".*?"/g, '' ) );\r
+ CKEDITOR.env.ie && contents && ( contents = contents.replace( /\s+data-cke-expando=".*?"/g, '' ) );\r
\r
this.contents = contents;\r
this.bookmarks = selection && selection.createBookmarks2( true );\r
- }\r
+\r
+ editor.fire( 'afterUndoImage' );\r
+ };\r
\r
// Attributes that browser may changing them when setting via innerHTML.\r
var protectedAttrs = /\b(?:href|src|name)="[^"]*?"/gi;\r
{\r
equals : function( otherImage, contentOnly )\r
{\r
+\r
var thisContents = this.contents,\r
otherContents = otherImage.contents;\r
\r
\r
if ( startedTyping || modifierSnapshot )\r
{\r
- var beforeTypeImage = new Image( this.editor );\r
+ var beforeTypeImage = new Image( this.editor ),\r
+ beforeTypeCount = this.snapshots.length;\r
\r
// Use setTimeout, so we give the necessary time to the\r
// browser to insert the character into the DOM.\r
\r
// In IE, we need to remove the expando attributes.\r
if ( CKEDITOR.env.ie )\r
- currentSnapshot = currentSnapshot.replace( /\s+_cke_expando=".*?"/g, '' );\r
+ currentSnapshot = currentSnapshot.replace( /\s+data-cke-expando=".*?"/g, '' );\r
\r
- if ( beforeTypeImage.contents != currentSnapshot )\r
+ // If changes have taken place, while not been captured yet (#8459),\r
+ // compensate the snapshot.\r
+ if ( beforeTypeImage.contents != currentSnapshot &&\r
+ beforeTypeCount == this.snapshots.length )\r
{\r
// It's safe to now indicate typing state.\r
this.typing = true;\r
*/\r
this.index = -1;\r
\r
- this.limit = this.editor.config.undoStackSize;\r
+ this.limit = this.editor.config.undoStackSize || 20;\r
\r
this.currentImage = null;\r
\r
\r
restoreImage : function( image )\r
{\r
+ // Bring editor focused to restore selection.\r
+ var editor = this.editor,\r
+ sel;\r
+\r
+ if ( image.bookmarks )\r
+ {\r
+ editor.focus();\r
+ // Retrieve the selection beforehand. (#8324)\r
+ sel = editor.getSelection();\r
+ }\r
+\r
this.editor.loadSnapshot( image.contents );\r
\r
if ( image.bookmarks )\r
- this.editor.getSelection().selectBookmarks( image.bookmarks );\r
+ sel.selectBookmarks( image.bookmarks );\r
else if ( CKEDITOR.env.ie )\r
{\r
// IE BUG: If I don't set the selection to *somewhere* after setting\r
// Update current image with the actual editor\r
// content, since actualy content may differ from\r
// the original snapshot due to dom change. (#4622)\r
- this.snapshots.splice( this.index, 1, ( this.currentImage = new Image( this.editor ) ) );\r
-\r
+ this.update();\r
this.fireChange();\r
},\r
\r
}\r
\r
return false;\r
+ },\r
+\r
+ /**\r
+ * Update the last snapshot of the undo stack with the current editor content.\r
+ */\r
+ update : function()\r
+ {\r
+ this.snapshots.splice( this.index, 1, ( this.currentImage = new Image( this.editor ) ) );\r
}\r
};\r
})();\r
/**\r
* The number of undo steps to be saved. The higher this setting value the more\r
* memory is used for it.\r
+ * @name CKEDITOR.config.undoStackSize\r
* @type Number\r
* @default 20\r
* @example\r
* config.undoStackSize = 50;\r
*/\r
-CKEDITOR.config.undoStackSize = 20;\r
\r
/**\r
* Fired when the editor is about to save an undo snapshot. This event can be\r
* @name CKEDITOR.editor#saveSnapshot\r
* @event\r
*/\r
+\r
+/**\r
+ * Fired before an undo image is to be taken. An undo image represents the\r
+ * editor state at some point. It's saved into an undo store, so the editor is\r
+ * able to recover the editor state on undo and redo operations.\r
+ * @name CKEDITOR.editor#beforeUndoImage\r
+ * @since 3.5.3\r
+ * @see CKEDITOR.editor#afterUndoImage\r
+ * @event\r
+ */\r
+\r
+/**\r
+ * Fired after an undo image is taken. An undo image represents the\r
+ * editor state at some point. It's saved into an undo store, so the editor is\r
+ * able to recover the editor state on undo and redo operations.\r
+ * @name CKEDITOR.editor#afterUndoImage\r
+ * @since 3.5.3\r
+ * @see CKEDITOR.editor#beforeUndoImage\r
+ * @event\r
+ */\r