Ticket #2768: 2768_4.patch

File 2768_4.patch, 6.5 KB (added by Martin Kou, 16 years ago)
  • _source/plugins/styles/plugin.js

     
    9898                };
    9999        };
    100100
     101        var applyStyle = function( document, remove )
     102        {
     103                // Get all ranges from the selection.
     104                var selection = document.getSelection();
     105                var ranges = selection.getRanges();
     106                var func = remove ? this.removeFromRange : this.applyToRange;
     107
     108                // Apply the style to the ranges.
     109                for ( var i = 0 ; i < ranges.length ; i++ )
     110                        func.call( this, ranges[ i ] );
     111
     112                // Select the ranges again.
     113                selection.selectRanges( ranges );
     114        };
     115
    101116        CKEDITOR.style.prototype =
    102117        {
    103118                apply : function( document )
    104119                {
    105                         // Get all ranges from the selection.
    106                         var selection = document.getSelection();
    107                         var ranges = selection.getRanges();
     120                        applyStyle.call( this, document, false );
     121                },
    108122
    109                         // Apply the style to the ranges.
    110                         for ( var i = 0 ; i < ranges.length ; i++ )
    111                                 this.applyToRange( ranges[ i ] );
    112 
    113                         // Select the ranges again.
    114                         selection.selectRanges( ranges );
     123                remove : function( document )
     124                {
     125                        applyStyle.call( this, document, true );
    115126                },
    116127
    117128                applyToRange : function( range )
     
    124135                                                : null ).call( this, range );
    125136                },
    126137
     138                removeFromRange : function( range )
     139                {
     140                        return ( this.removeFromRange =
     141                                                this.type == CKEDITOR.STYLE_INLINE ?
     142                                                        removeInlineStyle
     143                                                : null ).call( this, range );
     144                },
     145
    127146                /**
    128147                 * Get the style state inside an element path. Returns "true" if the
    129148                 * element is active in the path.
     
    359378
    360379                                        // Here we do some cleanup, removing all duplicated
    361380                                        // elements from the style element.
    362                                         removeFromElement( this, styleNode );
     381                                        removeFromInsideElement( this, styleNode );
    363382
    364383                                        // Insert it into the range position (it is collapsed after
    365384                                        // extractContents.
     
    389408                range.moveToBookmark( bookmark );
    390409        };
    391410
    392         var applyBlockStyle = function( range )
     411        var removeInlineStyle = function( range )
    393412        {
    394         };
     413                /*
     414                 * Make sure our range has included all "collpased" parent inline nodes so
     415                 * that our operation logic can be simpler.
     416                 */
     417                range.enlarge( CKEDITOR.ENLARGE_ELEMENT );
    395418
    396         // Removes a style from inside an element.
    397         var removeFromElement = function( style, element )
    398         {
    399                 var def = style._.definition;
    400                 var attribs = def.attributes;
    401                 var styles = def.styles;
     419                var bookmark = range.createBookmark(),
     420                        startNode = bookmark.startNode,
     421                        startPath = new CKEDITOR.dom.elementPath( startNode.getParent() );
    402422
    403                 var innerElements = element.getElementsByTag( style.element );
     423                if ( range.collapsed )
     424                {
     425                        /*
     426                         * If the range is collapsed, try to remove the style from all ancestor
     427                         * elements, until either a block boundary is reached, or the style is
     428                         * removed.
     429                         */
     430                        for ( var i = 0, element ; i < startPath.elements.length && ( element = startPath.elements[i] )  ; i++ )
     431                        {
     432                                if ( element == startPath.block || element == startPath.blockLimit )
     433                                        break;
    404434
    405                 for ( var i = innerElements.count() ; --i >= 0 ; )
     435                                if ( this.checkElementRemovable( element ) )
     436                                {
     437                                        removeFromElement( this, element );
     438                                        break;
     439                                }
     440                        }
     441                }
     442                else
    406443                {
    407                         var innerElement = innerElements.getItem( i );
     444                        /*
     445                         * Now our range isn't collapsed. Lets walk from the start node to the end
     446                         * node via DFS and remove the styles one-by-one.
     447                         */
     448                        var endNode = bookmark.endNode,
     449                                endPath = new CKEDITOR.dom.elementPath( endNode.getParent() );
     450                                currentNode = startNode;
    408451
    409                         for ( var attName in attribs )
     452                        // Find out the ancestor that needs to be broken down at startNode and endNode.
     453                        var breakStart = null, breakEnd = null;
     454                        for ( var i = 0 ; i < startPath.elements.length ; i++ )
    410455                        {
    411                                 // The 'class' element value must match (#1318).
    412                                 if ( attName == 'class' && innerElement.getAttribute( 'class' ) != attribs[ attName ] )
    413                                         continue;
    414 
    415                                 innerElement.removeAttribute( attName );
     456                                if ( this.checkElementRemovable( startPath.elements[ i ] ) )
     457                                {
     458                                        breakStart = startPath.elements[ i ];
     459                                        break;
     460                                }
    416461                        }
     462                        for ( var i = 0 ; i < endPath.elements.length ; i++ )
     463                        {
     464                                if ( this.checkElementRemovable( endPath.elements[ i ] ) )
     465                                {
     466                                        breakEnd = endPath.elements[ i ];
     467                                        break;
     468                                }
     469                        }
    417470
    418                         for ( var styleName in styles )
     471                        if ( breakEnd )
     472                                endNode.breakParent( breakEnd );
     473                        if ( breakStart )
     474                                startNode.breakParent( breakStart );
     475
     476                        // Now, do the DFS walk.
     477                        while ( ( currentNode = currentNode.getNextSourceNode() ) && !currentNode.equals( endNode ) )
    419478                        {
    420                                 innerElement.removeStyle( styleName );
     479                                if ( currentNode.type == CKEDITOR.NODE_ELEMENT )
     480                                        removeFromElement( this, currentNode );
    421481                        }
     482                }
     483               
     484                range.moveToBookmark( bookmark );
     485        };
    422486
    423                         removeNoAttribsElement( innerElement );
     487        var applyBlockStyle = function( range )
     488        {
     489        };
     490
     491        // Removes a style from an element itself, don't care about its subtree.
     492        var removeFromElement = function( style, element )
     493        {
     494                var def = style._.definition,
     495                        attributes = def.attributes,
     496                        styles = def.styles;
     497
     498                for ( var attName in attributes )
     499                {
     500                        // The 'class' element value must match (#1318).
     501                        if ( attName == 'class' && element.getAttribute( attName ) != attributes[ attName ] )
     502                                continue;
     503                        element.removeAttribute( attName );
    424504                }
     505
     506                for ( var styleName in styles )
     507                        element.removeStyle( styleName );
     508
     509                removeNoAttribsElement( element );
    425510        };
    426511
     512        // Removes a style from inside an element.
     513        var removeFromInsideElement = function( style, element )
     514        {
     515                var def = style._.definition;
     516                var attribs = def.attributes;
     517                var styles = def.styles;
     518
     519                var innerElements = element.getElementsByTag( style.element );
     520
     521                for ( var i = innerElements.count() ; --i >= 0 ; )
     522                        removeFromElement( style, innerElements.getItem( i ) );
     523        };
     524
    427525        // If the element has no more attributes, remove it.
    428526        var removeNoAttribsElement = function( element )
    429527        {
     
    596694        var doc = editor.document;
    597695
    598696        if ( doc )
    599                 this.style.apply( doc );
     697        {
     698                if ( this.state == CKEDITOR.TRISTATE_OFF )
     699                        this.style.apply( doc );
     700                else if ( this.state == CKEDITOR.TRISTATE_ON )
     701                        this.style.remove( doc );
     702        }
    600703
    601704        return !!doc;
    602705};
© 2003 – 2022, CKSource sp. z o.o. sp.k. All rights reserved. | Terms of use | Privacy policy