Ticket #6376: 6376_5.patch

File 6376_5.patch, 9.8 KB (added by Garry Yao, 9 years ago)
  • _source/plugins/bidi/plugin.js

     
    5252                        chromeRoot.removeClass( 'cke_mixed_dir_content' );
    5353        }
    5454
    55         function switchDir( element, dir, editor, state )
     55
     56        function getFullySelected( selection, elements )
    5657        {
    57                 var dirBefore = element.getComputedStyle( 'direction' );
     58                var selectedElement = selection.getCommonAncestor();
     59                while( selectedElement.type == CKEDITOR.NODE_ELEMENT
     60                                && !( selectedElement.getName() in elements )
     61                                && selectedElement.getParent().getChildCount() == 1
     62                        )
     63                        selectedElement = selectedElement.getParent();
    5864
    59                 element.removeStyle( 'direction' );
    60                 element.removeAttribute( 'dir' );
     65                return selectedElement.type == CKEDITOR.NODE_ELEMENT
     66                        && ( selectedElement.getName() in elements )
     67                        && selectedElement;
     68        }
     69
     70        function bidiCommand( dir, editor )
     71        {
     72                function switchDir( element, dir, database )
     73                {
     74                        // Check first whether one of the ancestors
     75                        // has already been styled.
     76                        var parent = element;
     77                        while ( ( parent = parent.getParent() ) && !parent.is( 'body' ) )
     78                        {
     79                                if ( parent.getCustomData( 'bidi_processed' ) )
     80                                {
     81                                        // Ancestor style must dominate.
     82                                        element.removeStyle( 'direction' );
     83                                        element.removeAttribute( 'dir' );
     84                                        return;
     85                                }
     86                        }
    6187
    62                 if ( state == CKEDITOR.TRISTATE_OFF && element.getComputedStyle( 'direction' ).toLowerCase() != dir )
     88                        var useComputedState = ( 'useComputedState' in editor.config ) ? editor.config.useComputedState : 1;
     89
     90                        var elementDir = useComputedState ? element.getComputedStyle( 'direction' )
     91                                : element.getStyle( 'direction' ) || element.hasAttribute( 'dir' );
     92
     93                        // Stop if direction is same as present.
     94                        if ( elementDir == dir )
     95                                return;
     96
     97                        // Reuse computedState if we already have it.
     98                        var dirBefore = useComputedState ? elementDir : element.getComputedStyle( 'direction' );
     99
     100                        // Clear direction on this element.
     101                        element.removeStyle( 'direction' );
     102
     103                        // Set new direction for this element.
    63104                        element.setAttribute( 'dir', dir );
    64105
    65                 // If the element direction changed, we need to switch the margins of
    66                 // the element and all its children, so it will get really reflected
    67                 // like a mirror. (#5910)
    68                 var dirAfter = element.getComputedStyle( 'direction' );
    69                 if ( dirAfter != dirBefore )
    70                 {
    71                         var range = new CKEDITOR.dom.range( element.getDocument() );
    72                         range.setStartBefore( element );
    73                         range.setEndAfter( element );
     106                        // If the element direction changed, we need to switch the margins of
     107                        // the element and all its children, so it will get really reflected
     108                        // like a mirror. (#5910)
     109                        if ( dir != dirBefore )
     110                        {
     111                                var range = new CKEDITOR.dom.range( element.getDocument() );
     112                                range.setStartBefore( element );
     113                                range.setEndAfter( element );
    74114
    75                         var walker = new CKEDITOR.dom.walker( range );
     115                                var walker = new CKEDITOR.dom.walker( range );
    76116
    77                         var node;
    78                         while ( ( node = walker.next() ) )
    79                         {
    80                                 if ( node.type == CKEDITOR.NODE_ELEMENT )
    81                                 {
    82                                         // A child with dir defined is to be ignored.
    83                                         if ( !node.equals( element ) && node.hasAttribute( 'dir' ) )
    84                                         {
    85                                                 range.setStartAfter( node );
    86                                                 walker = new CKEDITOR.dom.walker( range );
    87                                                 continue;
    88                                         }
     117                                var node;
     118                                while ( ( node = walker.next() ) )
     119                                {
     120                                        if ( node.type == CKEDITOR.NODE_ELEMENT )
     121                                        {
     122                                                // A child with dir defined is to be ignored.
     123                                                if ( !node.equals( element ) && node.hasAttribute( 'dir' ) )
     124                                                {
     125                                                        range.setStartAfter( node );
     126                                                        walker = new CKEDITOR.dom.walker( range );
     127                                                        continue;
     128                                                }
    89129
    90                                         // Switch the margins.
    91                                         var marginLeft = node.getStyle( 'margin-right' ),
    92                                                 marginRight = node.getStyle( 'margin-left' );
     130                                                // Switch the margins.
     131                                                var marginLeft = node.getStyle( 'margin-right' ),
     132                                                        marginRight = node.getStyle( 'margin-left' );
    93133
    94                                         marginLeft ? node.setStyle( 'margin-left', marginLeft ) : node.removeStyle( 'margin-left' );
    95                                         marginRight ? node.setStyle( 'margin-right', marginRight ) : node.removeStyle( 'margin-right' );
    96                                 }
    97                         }
    98                 }
     134                                                marginLeft ? node.setStyle( 'margin-left', marginLeft ) : node.removeStyle( 'margin-left' );
     135                                                marginRight ? node.setStyle( 'margin-right', marginRight ) : node.removeStyle( 'margin-right' );
     136                                        }
     137                                }
     138                        }
    99139
    100                 editor.forceNextSelectionCheck();
    101         }
     140                        editor.forceNextSelectionCheck();
    102141
    103         function getFullySelected( selection, elements )
    104         {
    105                 var selectedElement = selection.getCommonAncestor();
    106                 while( selectedElement.type == CKEDITOR.NODE_ELEMENT
    107                                 && !( selectedElement.getName() in elements )
    108                                 && selectedElement.getParent().getChildCount() == 1
    109                         )
    110                         selectedElement = selectedElement.getParent();
     142                        CKEDITOR.dom.element.setMarker( database, element, 'bidi_processed', 1 );
    111143
    112                 return selectedElement.type == CKEDITOR.NODE_ELEMENT
    113                         && ( selectedElement.getName() in elements )
    114                         && selectedElement;
    115         }
     144                        return true;
     145                }
    116146
    117         function bidiCommand( dir )
    118         {
    119                 return function( editor )
    120                 {
     147                return function()
     148                {
    121149                        var selection = editor.getSelection(),
    122150                                enterMode = editor.config.enterMode,
    123151                                ranges = selection.getRanges();
    124152
    125153                        if ( ranges && ranges.length )
    126154                        {
     155                                var database = {};
    127156                                // Apply do directly selected elements from guardElements.
    128157                                var selectedElement = ranges[ 0 ].getEnclosedNode();
    129158
     
    133162                                        )
    134163                                        selectedElement = getFullySelected( selection, guardElements );
    135164
    136                                 if ( selectedElement )
    137                                 {
    138                                         if ( !selectedElement.isReadOnly() )
    139                                                 switchDir( selectedElement, dir, editor, this.state );
    140                                 }
    141                                 else
    142                                 {
    143                                         // Creates bookmarks for selection, as we may split some blocks.
    144                                         var bookmarks = selection.createBookmarks();
     165                                if ( selectedElement && !selectedElement.isReadOnly() )
     166                                                switchDir( selectedElement, dir, database );
     167
     168                                // Creates bookmarks for selection, as we may split some blocks.
     169                                var bookmarks = selection.createBookmarks();
    145170
    146                                         var iterator,
    147                                                 block;
     171                                var iterator,
     172                                        block;
    148173
    149                                         for ( var i = ranges.length - 1 ; i >= 0 ; i-- )
    150                                         {
    151                                                 // Array of elements processed as guardElements.
    152                                                 var processedElements = [];
    153                                                 // Walker searching for guardElements.
    154                                                 var walker = new CKEDITOR.dom.walker( ranges[ i ] );
    155                                                 walker.evaluator = function( node ){
    156                                                         return node.type == CKEDITOR.NODE_ELEMENT
    157                                                                 && node.getName() in guardElements
    158                                                                 && !( node.getName() == ( enterMode == CKEDITOR.ENTER_P ) ? 'p' : 'div'
    159                                                                         && node.getParent().type == CKEDITOR.NODE_ELEMENT
    160                                                                         && node.getParent().getName() == 'blockquote'
    161                                                                 );
    162                                                 };
     174                                for ( var i = ranges.length - 1 ; i >= 0 ; i-- )
     175                                {
     176                                        // Array of elements processed as guardElements.
     177                                        var processedElements = [];
     178                                        // Walker searching for guardElements.
     179                                        var walker = new CKEDITOR.dom.walker( ranges[ i ] );
     180                                        walker.evaluator = function( node ){
     181                                                return node.type == CKEDITOR.NODE_ELEMENT
     182                                                        && node.getName() in guardElements
     183                                                        && !( node.getName() == ( enterMode == CKEDITOR.ENTER_P ) ? 'p' : 'div'
     184                                                                && node.getParent().type == CKEDITOR.NODE_ELEMENT
     185                                                                && node.getParent().getName() == 'blockquote'
     186                                                        );
     187                                        };
    163188
    164                                                 while ( ( block = walker.next() ) )
    165                                                 {
    166                                                         switchDir( block, dir, editor, this.state );
    167                                                         processedElements.push( block );
    168                                                 }
     189                                        while ( ( block = walker.next() ) )
     190                                                switchDir( block, dir, database );
    169191
    170                                                 iterator = ranges[ i ].createIterator();
    171                                                 iterator.enlargeBr = enterMode != CKEDITOR.ENTER_BR;
     192                                        iterator = ranges[ i ].createIterator();
     193                                        iterator.enlargeBr = enterMode != CKEDITOR.ENTER_BR;
    172194
    173                                                 while ( ( block = iterator.getNextParagraph( enterMode == CKEDITOR.ENTER_P ? 'p' : 'div' ) ) )
    174                                                 {
    175                                                         if ( block.isReadOnly() )
    176                                                                 continue;
    177 
    178                                                         var _break = 0;
    179 
    180                                                         // Check if block have been already processed by the walker above.
    181                                                         for ( var ii = 0; ii < processedElements.length; ii++ )
    182                                                         {
    183                                                                 var parent = block.getParent();
    184 
    185                                                                 while( parent && parent.getName() != 'body' )
    186                                                                 {
    187                                                                         if ( ( parent.$.isSameNode && parent.$.isSameNode( processedElements[ ii ].$ ) )
    188                                                                                         || parent.$ == processedElements[ ii ].$ )
    189                                                                         {
    190                                                                                 _break = 1;
    191                                                                                 break;
    192                                                                         }
    193                                                                         parent = parent.getParent();
    194                                                                 }
     195                                        while ( ( block = iterator.getNextParagraph( enterMode == CKEDITOR.ENTER_P ? 'p' : 'div' ) ) )
     196                                                !block.isReadOnly() && switchDir( block, dir, database );
     197                                }
    195198
    196                                                                 if ( _break )
    197                                                                         break;
    198                                                         }
     199                                CKEDITOR.dom.element.clearAllMarkers( database );
    199200
    200                                                         if ( !_break )
    201                                                         {
    202                                                                 switchDir( block, dir, editor, this.state );
    203                                                         }
    204                                                 }
    205                                         }
    206 
    207                                         editor.forceNextSelectionCheck();
    208                                         // Restore selection position.
    209                                         selection.selectBookmarks( bookmarks );
    210                                 }
     201                                editor.forceNextSelectionCheck();
     202                                // Restore selection position.
     203                                selection.selectBookmarks( bookmarks );
    211204
    212205                                editor.focus();
    213206                        }
     
    235228
    236229                        var lang = editor.lang.bidi;
    237230
    238                         addButtonCommand( 'BidiLtr', lang.ltr, 'bidiltr', bidiCommand( 'ltr' ) );
    239                         addButtonCommand( 'BidiRtl', lang.rtl, 'bidirtl', bidiCommand( 'rtl' ) );
     231                        addButtonCommand( 'BidiLtr', lang.ltr, 'bidiltr', bidiCommand( 'ltr', editor ) );
     232                        addButtonCommand( 'BidiRtl', lang.rtl, 'bidirtl', bidiCommand( 'rtl', editor ) );
    240233
    241234                        editor.on( 'selectionChange', onSelectionChange );
    242235                }
© 2003 – 2019 CKSource – Frederico Knabben. All rights reserved. | Terms of use | Privacy policy