Ticket #2763: 2763_4.patch

File 2763_4.patch, 14.7 KB (added by Garry Yao, 14 years ago)

Revise to apply to trunk

  • _source/plugins/editingblock/plugin.js

     
    138138
    139139                modeEditor.load( holderElement, data || this.getData() );
    140140        };
    141 
     141       
     142        /**
     143         * @private Get the current blockediting mode of this editor
     144         * @param mode The name of the specified mode, by default the current mode.
     145         * @return {Object}  The mode editor definition.
     146         */
     147        CKEDITOR.editor.prototype.getMode = function( mode )
     148        {
     149                return this._.modes && this._.modes[ mode || this.mode ];
     150        };
     151       
    142152        /**
    143153         * Moves the selection focus to the editing are space in the editor.
    144154         */
  • _source/plugins/toolbar/plugin.js

     
    210210                'NewPage', '-',
    211211                'Bold', 'Italic', 'Underline', 'Strike', '-',
    212212                'Subscript', 'Superscript', '-',
     213                'Undo', 'Redo', '-',
    213214                'SelectAll', 'RemoveFormat', '-',
    214215                'Smiley', 'HorizontalRule', 'SpecialChar', 'PageBreak'
    215216        ]
  • _source/plugins/selection/plugin.js

     
    618618                                                sel.addRange( nativeRange );
    619619                                        }
    620620                                },
    621 
    622                 createBookmarks : function()
     621        /**
     622                 * This method is a delegate to ceate bookmark for every ranges in this selection.
     623                 *
     624                 * @see CKEDITOR.dom.range::createBookmark
     625                 */
     626                createBookmarks : function ( serializable )
    623627                {
    624628                        var retval = [],
    625629                                ranges = this.getRanges();
     
    624628                        var retval = [],
    625629                                ranges = this.getRanges();
    626630                        for ( var i = 0 ; i < ranges.length ; i++ )
    627                                 retval.push( ranges[i].createBookmark() );
     631                                retval.push( ranges[ i ].createBookmark( serializable ) );
    628632                        return retval;
    629633                },
    630634
  • _source/plugins/undoredo/plugin.js

     
     1/*
     2 * Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
     3 * For licensing, see LICENSE.html or http://ckeditor.com/license
     4 */
     5
     6/**
     7 * @fileOverview Undo/Redo system for saving shapshot for document modification
     8 *               and other recordable changes.
     9 */
     10CKEDITOR.plugins.add( 'undoredo' ,
     11/**
     12 * @implements CKEDITOR.pluginDefinition The undo/redo feature for wysiwygarea
     13 *             mode
     14 */
     15{
     16
     17        requires : [ 'selection', 'wysiwygarea' ],
     18        init : function ( editor )
     19        {
     20                       
     21                var urm = new UndoRedoManager( editor );
     22                function recordCommand ( evt )
     23                {
     24                        var event /* {FCKEDITOR.command.Event} */= evt.data;
     25                        if ( event.command.supportUndoRedo !== false // ingore mode change
     26                                        // command
     27                                        && event.name !== 'source'
     28                                        && event.name !== 'wysiwyg'
     29                                        && urm.enabled )
     30                        {
     31                                urm.save( evt.name === 'beforeCommandExec' ? true : false );
     32                        }
     33                }
     34
     35                editor.on( 'beforeCommandExec' , recordCommand );
     36                editor.on( 'afterCommandExec' , recordCommand );
     37
     38                // sensitive to mode change, only appliable for 'wysiwyg' mode
     39                editor.on( 'mode' , function ( currentMode )
     40                {
     41                        urm.enabled = editor.getMode().name === 'wysiwyg';
     42                } );
     43
     44                editor.addCommand( 'undo' ,
     45                /**
     46                 * @implements CKEDITOR.commandDefinition Rollback to last modification
     47                 *             of this document
     48                 */
     49                {
     50
     51                        exec : function() {
     52                                if (urm.undo()) {
     53                                        this.fire('AfterUndo');
     54                                        // TODO: fire 'selectionchange'
     55                                }
     56                        },
     57                        supportUndoRedo : false
     58                } );
     59
     60                editor.addCommand( 'redo' ,
     61                /**
     62                 * @implements CKEDITOR.commandDefinition Retrieve to next modification
     63                 *             of this document
     64                 */
     65                {
     66                        exec : function() {
     67                                if (urm.redo()) {
     68                                        this.fire('AfterRedo');
     69                                        // TODO: fire 'selectionchange'
     70                                }
     71                        },
     72                        supportUndoRedo : false
     73                } );
     74               
     75                editor.ui.addButton( 'Undo',
     76                        {
     77                                label : editor.lang.undo,
     78                                command : 'undo'
     79                        });
     80                editor.ui.addButton( 'Redo',
     81                        {
     82                                label : editor.lang.redo,
     83                                command : 'redo'
     84                        });
     85        }
     86} );
     87
     88/**
     89 * @constructor Main logic for Redo/Undo feature
     90 * @related FCKUndo in v2
     91 */
     92function UndoRedoManager ( editor )
     93{
     94
     95        /**
     96         * @field Whether undo system is usable decided by envoriment
     97         */
     98        this.enabled = false;
     99
     100        var UNDO_NUM_LIMIT = 20;
     101
     102        /**
     103         * Stack for all the undo and redo snapshots, they're always created/removed
     104         * in consistency.
     105         *
     106         * @type {Array<DocumentImage>}
     107         *
     108         */
     109        var undoSnaps = [] , redoSnaps = [];
     110
     111        /**
     112         * Current snapshot history index
     113         */
     114        var index = 0; // First capture start from 1
     115
     116        /**
     117         * @constructor DocumentImage - A snapshot image which represent the current
     118         *              document status.
     119         */
     120        function DocumentImage ( )
     121        {
     122
     123                var bms , ranges , cWithBm , c;
     124
     125                c = editor.getMode( 'wysiwyg' ).getSnapshotData();
     126                bms = editor.document.getSelection().createBookmarks( true );
     127                ranges = editor.document.getSelection().getRanges(); // Get ranges
     128                // from cache
     129                cWithBm = editor.getMode( 'wysiwyg' ).getSnapshotData() // Get content along
     130                // with bookmark
     131                editor.document.getSelection().selectBookmarks( bms );
     132                // restore
     133                // selection by
     134                // the bookmark
     135                // and we
     136                // also
     137                // destroy the nodes in document
     138                return {
     139                        'content' : /** {String} original document string */
     140                        c,
     141                        'dirtyContent' :
     142                        /**
     143                         * {String} document content string with bookmarks
     144                         */
     145                        cWithBm,
     146                        'bookmark' /** {Array<CKEDITOR.dom.range.Bookmark>} */
     147                        :bms,
     148                        equals :
     149                        /**
     150                         * Compare if two document snapshot are the same, this is only
     151                         * content comparison with bookmarks striped. (
     152                         *
     153                         * @img {DocumentImage} The other image to compare with
     154                         */
     155                        function ( img )
     156                        {
     157                                return this.content == img.content;
     158                        }
     159                }
     160        }
     161
     162        /**
     163         * @method Save a snapshot of document image for later retrieve, content
     164         *         being saved as raw html string, while selection saved as a
     165         *         lightweight bookmark.
     166         */
     167        this.save = function ( isFront )
     168        {
     169                var sns = isFront ? undoSnaps : redoSnaps;
     170
     171                if ( index == UNDO_NUM_LIMIT )
     172                {
     173                        sns.unshift(); // Die out earlier ones.
     174                }
     175
     176                sns.splice( index , sns.length - index ); // Drop older snaps
     177
     178                var img = new DocumentImage();
     179                if ( sns.length && img.equals( sns[ sns.length - 1 ] ) ) // duplicate
     180                        // examination
     181                        return;
     182
     183                sns.push( img );
     184
     185                if ( !isFront )
     186                        index++; // increase when command has been fully recorded.
     187        }
     188
     189        function restoreImage ( index, isUndo )
     190        {
     191                var img;
     192                img = isUndo ? undoSnaps[ index ] : redoSnaps[ index ];
     193                if ( img.content )
     194                {
     195                        editor.getMode( 'wysiwyg' ).loadSnapshotData( img.dirtyContent );
     196                        if ( img.bookmark )
     197                        {
     198                                editor.document.getSelection().selectBookmarks( img.bookmark );
     199                        }
     200                }
     201        }
     202
     203        /**
     204         * Check the current state of redo
     205         *
     206         * @return {Boolean} Whether the document has previous state to retrieve
     207         */
     208        this.redoAble = function ( )
     209        {
     210                return index < redoSnaps.length;
     211        }
     212
     213        /**
     214         * Check the current state of undo
     215         *
     216         * @return {Boolean} Whether the document has future state to restore
     217         */
     218        this.undoAble = function ( )
     219        {
     220                return index > 0
     221        }
     222        /**
     223         * Perform undo on current index.
     224         *
     225         * @method
     226         */
     227        this.undo = function ( )
     228        {
     229                if ( this.undoAble() )
     230                {
     231                        restoreImage( --index , true ); // retrieve previous one from undo
     232                        // history
     233                }
     234                else
     235                        return false;
     236        }
     237
     238        /**
     239         * Perform redo on current index.
     240         *
     241         * @method
     242         */
     243        this.redo = function ( )
     244        {
     245                if ( this.redoAble() )
     246                {
     247                        restoreImage( index++ , false ); // retrieve next one from redo
     248                        // history
     249                }
     250                else
     251                        return false;
     252        }
     253
     254}
  • _source/core/commanddefinition.js

     
    3333 *     }
    3434 * });
    3535 */
     36 
     37/**
     38 * Whether the command need to be hooked into the redo/undo system.
     39 * @name  CKEDITOR.commandDefinition.supportUndoRedo
     40 * @type {Boolean} If not defined or 'true' both hook into undo system, set it to 'false' explicitly  keep it out. 
     41 * @field
     42 * @example
     43 *  editorInstance.addCommand( 'sample',
     44 * {
     45 *     CKEDITOR.commandDefinition.supportUndoRedo : false    //declare this command does not support undo/redo 
     46 * });
     47 */
  • _source/core/dom/range.js

     
    409409                        return docFrag;
    410410                },
    411411
    412                 // This is an "intrusive" way to create a bookmark. It includes <span> tags
    413                 // in the range boundaries. The advantage of it is that it is possible to
    414                 // handle DOM mutations when moving back to the bookmark.
    415                 // Attention: the inclusion of nodes in the DOM is a design choice and
    416                 // should not be changed as there are other points in the code that may be
    417                 // using those nodes to perform operations. See GetBookmarkNode.
    418                 createBookmark : function()
     412                /**
     413                 * This is an "intrusive" way to create a bookmark. It includes <span>
     414                 * tags in the range boundaries. The advantage of it is that it is
     415                 * possible to handle DOM mutations when moving back to the bookmark.
     416                 * Attention: the inclusion of nodes in the DOM is a design choice.
     417                 *
     418                 * @param serializeable {Boolean} If set to true will record the bookmark with startNode/endNode IDs for serializing purpose.
     419                 */
     420                createBookmark : function(serializeable)
    419421                {
    420                         var startNode, endNode;
     422                        var startNode , endNode;
    421423                        var clone;
    422424
    423425                        startNode = this.document.createElement( 'span' );
    424                         startNode.setAttribute( '_fck_bookmark', 1 );
    425                         startNode.setStyle( 'display', 'none' );
     426                        startNode.setAttribute( '_fck_bookmark' , 1 );
     427                        startNode.setStyle( 'display' , 'none' );
    426428
    427429                        // For IE, it must have something inside, otherwise it may be
    428430                        // removed during DOM operations.
     
    452454                        else
    453455                                this.moveToPosition( startNode, CKEDITOR.POSITION_AFTER_END );
    454456
     457                        if ( serializeable )
     458                        {
     459                                startNode.setAttribute( 'id' , ( new Date() ).valueOf()
     460                                                + Math.floor( Math.random() * 1000 ) + 'S' );
     461                                if ( endNode )
     462                                        endNode.setAttribute( 'id' , ( new Date() ).valueOf()
     463                                                        + Math.floor( Math.random() * 1000 ) + 'E' );
     464                        }
    455465                        return {
    456                                 startNode : startNode,
    457                                 endNode : endNode
     466                                startNode :serializeable ? startNode.getAttribute( 'id' )
     467                                                : startNode,
     468                                endNode :endNode ? ( serializeable ? endNode
     469                                                .getAttribute( 'id' ) : endNode ) : null
    458470                        };
    459471                },
    460472
     473                /**
     474                 * Move the range boundaries to where the bookmarks indicated.
     475                 *
     476                 * @see CKEDITOR.dom.range::createBookmark
     477                 * @param {Object} bookmark
     478                 *
     479                 */
    461480                moveToBookmark : function( bookmark )
    462481                {
    463                         // Set the range start at the bookmark start node position.
    464                         this.setStartBefore( bookmark.startNode );
     482                        var startNode = bookmark.startNode , endNode = bookmark.endNode;
     483
     484                        // Set the range startNodeart at the bookmark startNodeart node position.
     485                        this.setStartBefore( typeof startNode === 'string' ? ( startNode = this.document
     486                                        .getById( startNode ) ) : startNode );
    465487
    466488                        // Remove it, because it may interfere in the setEndBefore call.
    467                         bookmark.startNode.remove();
     489                        startNode.remove();
    468490
    469491                        // Set the range end at the bookmark end node position, or simply
    470492                        // collapse it if it is not available.
    471                         var endNode = bookmark.endNode;
    472493                        if ( endNode )
    473494                        {
    474                                 this.setEndBefore( endNode );
     495                                this.setEndBefore( typeof endNode === 'string' ?
     496                                                ( endNode = this.document.getById( endNode ) )
     497                                                : endNode );
    475498                                endNode.remove();
    476499                        }
    477500                        else
  • _source/core/editor.js

     
    386386                execCommand : function( commandName, data )
    387387                {
    388388                        var command = this.getCommand( commandName );
     389                        var exeResult;
     390                        var commandEvent =
     391
     392                        /**
     393                         * The event data for this command
     394                         * @type FCKEDITOR.command.Event
     395                         */
     396                        {
     397                                name :commandName,
     398                                command :command
     399                        };
    389400                        if ( command && command.state != CKEDITOR.TRISTATE_DISABLED )
    390                                 return command.exec( this, data );
     401                        {
     402                                this.fire( 'beforeCommandExec' , commandEvent );
     403                                exeResult = command.exec( this , data );
     404                                this.fire( 'afterCommandExec' , commandEvent );
     405                                return exeResult;
     406                        }
    391407
    392408                        // throw 'Unknown command name "' + commandName + '"';
    393409                        return false;
  • _source/core/config.js

     
    146146         * @example
    147147         * config.plugins = 'basicstyles,button,htmldataprocessor,toolbar,wysiwygarea';
    148148         */
    149         plugins : 'basicstyles,button,elementspath,horizontalrule,htmldataprocessor,keystrokes,newpage,pagebreak,removeformat,smiley,sourcearea,specialchar,tab,toolbar,wysiwygarea',
     149        plugins : 'basicstyles,button,elementspath,horizontalrule,htmldataprocessor,keystrokes,newpage,pagebreak,removeformat,smiley,sourcearea,specialchar,tab,toolbar,wysiwygarea,undoredo',
    150150
    151151        /**
    152152         * The theme to be used to build the UI.
  • _source/lang/en.js

     
    4242        horizontalrule  : 'Insert Horizontal Line',
    4343        pagebreak               : 'Insert Page Break',
    4444        unlink                  : 'Unlink',
     45        undo                    : 'Undo',
     46        redo                    : 'Redo',
    4547
    4648        // Common messages and labels.
    4749        common :
  • _source/skins/default/toolbar.css

     
    305305{
    306306        background-position: 0 -880px;
    307307}
     308.cke_skin_default a.cke_button_undo .cke_icon
     309{
     310        background-position: 0 -208px;
     311}
     312.cke_skin_default a.cke_button_redo .cke_icon
     313{
     314        background-position: 0 -224px;
     315}
© 2003 – 2022, CKSource sp. z o.o. sp.k. All rights reserved. | Terms of use | Privacy policy