Ticket #3475: 3475_4.patch

File 3475_4.patch, 9.0 KB (added by Garry Yao, 11 years ago)
  • _source/plugins/styles/plugin.js

     
    119119                {
    120120                        applyStyle.call( this, document, true );
    121121                },
    122 
     122               
     123                /**
     124                 * Apply the current style to the specified range.
     125                 * Note : the range will be mangled after this method,
     126                 * so the range should be bookmarked before invoking it.
     127                 *
     128                 * @param {CKEDITOR.dom.range} range
     129                 * @example
     130                 * // Apply style defined as 'mystyle' to a range.
     131                 * var style = new CKEDITOR.style( editor.config.mystyle );
     132                 * var bookmark = range.createBookmark();
     133                 * style.spplyToRange( range );
     134                 * range.moveToBookmark( bookmark );
     135                 */
    123136                applyToRange : function( range )
    124137                {
    125138                        return ( this.applyToRange =
     
    130143                                                : null ).call( this, range );
    131144                },
    132145
     146                /**
     147                 * @see {@link CKEDITOR.style.applyToRange}
     148                 */
    133149                removeFromRange : function( range )
    134150                {
    135151                        return ( this.removeFromRange =
     
    305321                // Get the DTD definition for the element. Defaults to "span".
    306322                var dtd = CKEDITOR.dtd[ elementName ] || ( isUnknownElement = true, CKEDITOR.dtd.span );
    307323
    308                 // Bookmark the range so we can re-select it after processing.
    309                 var bookmark = range.createBookmark();
    310 
    311324                // Expand the range.
    312325                range.enlarge( CKEDITOR.ENLARGE_ELEMENT );
    313326                range.trim();
     
    503516                        }
    504517                }
    505518
    506 //              this._FixBookmarkStart( startNode );
    507 
    508                 range.moveToBookmark( bookmark );
    509519        }
    510520
    511521        function removeInlineStyle( range )
     
    10301040
    10311041        function applyStyle( document, remove )
    10321042        {
    1033                 // Get all ranges from the selection.
    1034                 var selection = document.getSelection();
    1035                 var ranges = selection.getRanges();
    1036                 var func = remove ? this.removeFromRange : this.applyToRange;
    1037 
    1038                 // Apply the style to the ranges.
    1039                 for ( var i = 0 ; i < ranges.length ; i++ )
    1040                         func.call( this, ranges[ i ] );
    1041 
    1042                 // Select the ranges again.
    1043                 selection.selectRanges( ranges );
     1043                // Creating bookmarks first, since the ranges might be dirty later then.
     1044                var selection = document.getSelection(),
     1045                        func = remove ? this.removeFromRange : this.applyToRange;
     1046                selection.forEachRange( CKEDITOR.tools.bind( func, this ) );
    10441047        }
    10451048})();
    10461049
  • _source/plugins/find/dialogs/find.js

     
    279279                                        this.removeHighlight();
    280280
    281281                                // Apply the highlight.
    282                                 var range = this.toDomRange();
     282                                var range = this.toDomRange(),
     283                                        bookmark = range.createBookmark();
    283284                                highlightStyle.applyToRange( range );
     285                                range.moveToBookmark( bookmark );
    284286                                this._.highlightRange = range;
    285287
    286288                                // Scroll the editor to the highlighted area.
     
    301303                                if ( !this._.highlightRange )
    302304                                        return;
    303305
     306                                var bookmark = this._.highlightRange.createBookmark();
    304307                                highlightStyle.removeFromRange( this._.highlightRange );
     308                                this._.highlightRange.moveToBookmark( bookmark );
    305309                                this.updateFromDomRange( this._.highlightRange );
    306310                                this._.highlightRange = null;
    307311                        },
  • _source/plugins/selection/plugin.js

     
    868868                createBookmarks : function( serializable )
    869869                {
    870870                        var retval = [],
    871                                 ranges = this.getRanges();
    872                         for ( var i = 0 ; i < ranges.length ; i++ )
    873                                 retval.push( ranges[i].createBookmark( serializable ) );
     871                                ranges = this.getRanges(),
     872                                length = ranges.length;
     873                        // Adding bookmark in reverse order to avoid interacting.
     874                        for ( var i = length -1 ; i  >= 0 ; i-- )
     875                                // Defer the bookmark updates later after all ranges get processed.
     876                                retval.push( ranges[ i ].createBookmark( serializable, true ) );
     877                       
     878                        // Update all ranges to reflect the changes from bookmark adding.(#3475)
     879                        for ( i = length -1 ; i >= 0 ; i-- )
     880                                ranges[ i ].moveToBookmark( retval[ i ], false );
     881                               
     882                        // Revert both back to sequenced order.
     883                        ranges.reverse();
     884                        retval.reverse();
     885                       
     886                        // Generally it's enough to just update ranges caches.
     887                        this._.cache.ranges = ranges;
    874888                        return retval;
    875889                },
    876890
     
    887901
    888902                selectBookmarks : function( bookmarks )
    889903                {
    890                         var ranges = [];
    891                         for ( var i = 0 ; i < bookmarks.length ; i++ )
     904                        var ranges = [], l = bookmarks.length;
     905
     906                        // Removing bookmarks in sequence order to avoid interacting.
     907                        for ( var i = 0 ; i < l ; i++ )
    892908                        {
    893909                                var range = new CKEDITOR.dom.range( this.document );
    894                                 range.moveToBookmark( bookmarks[i] );
     910                                range.moveToBookmark( bookmarks[ i ] );
    895911                                ranges.push( range );
    896912                        }
    897913                        this.selectRanges( ranges );
     
    896912                        }
    897913                        this.selectRanges( ranges );
    898914                        return this;
     915                },
     916               
     917                /**
     918                 *  Iterating over all the selected ranges, supply the
     919                 *  processor funtion with each range.
     920                 *  Note : Use this function only when the processor is devastative to the DOM,
     921                 *  it will guarantee every range is up-to-date after the processing.
     922                 *  @param { Funtion} processor The processor function, been invoked with
     923                 *  {@param CKEDITOR.dom.range} and {@param CKEDITOR.dom.selection}.
     924                 *  @example
     925                 *  selection.forEachRange( function( range )
     926                 *  {
     927                 *      // Some dirty manupulation...
     928                 *              range.insertNode( document.createElement( 'hr' ) );
     929                 *      } );
     930                 */
     931                forEachRange : function( processor )
     932                {
     933                        // Creating bookmarks first, since the ranges might be dirty later then.
     934                        var bookmarks = this.createBookmarks(),
     935                        ranges = this.getRanges();
     936       
     937                        for ( var i = 0, j ; i < ranges.length ; i++ )
     938                        {
     939                                processor( ranges[ i ], this );
     940                                // Update following ranges to resist dom changes.(#3475)
     941                                for ( j = i ; j < ranges.length ; j++ ) {
     942                                        ranges[ j ].moveToBookmark( bookmarks[ j ], false );
     943                                }
     944                        }
     945       
     946                        this.selectBookmarks( bookmarks );
    899947                }
    900948        };
    901949})();
  • _source/core/dom/range.js

     
    363363                 *              must contain ids, which can be used to restore the range even
    364364                 *              when these nodes suffer mutations (like a clonation or innerHTML
    365365                 *              change).
     366                 * @param {Boolean} [deferUpdate] Whether update the range to reflect
     367                 *      the inserting of bookmark nodes or manually update it later.
    366368                 * @returns {Object} And object representing a bookmark.
    367369                 */
    368                 createBookmark : function( serializable )
     370                createBookmark : function( serializable , deferUpdate )
    369371                {
    370372                        var startNode, endNode;
    371373                        var baseId;
     
    403405                        clone.collapse( true );
    404406                        clone.insertNode( startNode );
    405407
    406                         // Update the range position.
    407                         if ( endNode )
    408                         {
    409                                 this.setStartAfter( startNode );
    410                                 this.setEndBefore( endNode );
    411                         }
    412                         else
    413                                 this.moveToPosition( startNode, CKEDITOR.POSITION_AFTER_END );
    414 
    415                         return {
     408                        var retval = {
    416409                                startNode : serializable ? baseId + 'S' : startNode,
    417410                                endNode : serializable ? baseId + 'E' : endNode,
    418411                                serializable : serializable
     
    417410                                endNode : serializable ? baseId + 'E' : endNode,
    418411                                serializable : serializable
    419412                        };
     413
     414                        if ( !deferUpdate )
     415                                this.moveToBookmark( retval, false );
     416
     417                        return retval;
    420418                },
     419               
    421420
    422421                /**
    423422                 * Creates a "non intrusive" and "mutation sensible" bookmark. This
     
    512511                                is2                     : true          // It's a createBookmark2 bookmark.
    513512                        };
    514513                },
    515 
    516                 moveToBookmark : function( bookmark )
     514               
     515                /**
     516                 *  Move the range position to what indicate by the bookmark and
     517                 *  optionally remove the bookmark nodes.
     518                 *  @param {Object} bookmark Any bookmark created via
     519                 *  {@link CKEDITOR.dom.range::createBookmark} OR
     520                 *  {@link CKEDITOR.dom.range.createBookmark2} functions.
     521                 *  @param {Boolean} [dropNodes ] Whether remove the bookmark nodes after
     522                 *  move to the destination position.(defaults to be 'true')
     523                */
     524                moveToBookmark : function( bookmark, dropNodes )
    517525                {
    518526                        if ( bookmark.is2 )             // Created with createBookmark2().
    519527                        {
     
    544552                                this.setStartBefore( startNode );
    545553
    546554                                // Remove it, because it may interfere in the setEndBefore call.
    547                                 startNode.remove();
     555                                if ( dropNodes !== false )
     556                                        startNode.remove();
    548557
    549558                                // Set the range end at the bookmark end node position, or simply
    550559                                // collapse it if it is not available.
     
    551560                                if ( endNode )
    552561                                {
    553562                                        this.setEndBefore( endNode );
    554                                         endNode.remove();
     563                                        if ( dropNodes !== false )
     564                                                endNode.remove();
    555565                                }
    556566                                else
    557567                                        this.collapse( true );
© 2003 – 2019 CKSource – Frederico Knabben. All rights reserved. | Terms of use | Privacy policy