Ticket #8248: 8248_4.patch

File 8248_4.patch, 9.5 KB (added by Garry Yao, 8 years ago)
  • _source/core/dom/walker.js

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
     
    446446                };
    447447        };
    448448
     449        CKEDITOR.dom.walker.bogus = function( type, isReject )
     450        {
     451                function nonEmpty( node )
     452                {
     453                        return !isWhitespaces( node ) && !isBookmark( node );
     454                }
     455
     456                return function( node )
     457                {
     458                        var parent = node.getParent(),
     459                                isBogus = !CKEDITOR.env.ie ? node.is && node.is( 'br' ) :
     460                                          node.getText && tailNbspRegex.test( node.getText() );
     461
     462                        isBogus = isBogus && parent.isBlockBoundary() && !!parent.getLast( nonEmpty );
     463
     464                        return !! ( isReject ^ isBogus );
     465                };
     466        };
     467
    449468        var tailNbspRegex = /^[\t\r\n ]*(?:&nbsp;|\xa0)$/,
    450469                isWhitespaces = CKEDITOR.dom.walker.whitespaces(),
    451470                isBookmark = CKEDITOR.dom.walker.bookmark(),
  • _source/plugins/list/plugin.js

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
     
    1414
    1515        var whitespaces = CKEDITOR.dom.walker.whitespaces(),
    1616                bookmarks = CKEDITOR.dom.walker.bookmark(),
    17                 nonEmpty = function( node ){ return !( whitespaces( node ) || bookmarks( node ) ); };
     17                nonEmpty = function( node ){ return !( whitespaces( node ) || bookmarks( node ) );},
     18                blockBogus = CKEDITOR.dom.walker.bogus();
    1819
    1920        function cleanUpDirection( element )
    2021        {
     
    495496
    496497        var elementType = CKEDITOR.dom.walker.nodeType( CKEDITOR.NODE_ELEMENT );
    497498        // Merge list items with direction preserved. (#7448)
    498         function mergeListItems( from, into, toHead )
     499        function mergeListItems( from, into, refNode, toHead )
    499500        {
    500501                var child, itemDir;
    501502                while ( child = from.getFirst( elementType ) )
    502503                {
    503504                        if ( ( itemDir = child.getDirection( 1 ) ) !== into.getDirection( 1 ) )
    504505                                child.setAttribute( 'dir', itemDir );
    505                         into.append( child.remove(), toHead );
     506
     507                        child.remove();
     508
     509                        refNode ?
     510                                child[ toHead ? 'insertBefore' : 'insertAfter' ]( refNode ) :
     511                                into.append( child, toHead  );
    506512                }
    507513        }
    508514
     
    661667                                                 sibling.getName() == listCommand.type )
    662668                                        {
    663669                                                // Move children order by merge direction.(#3820)
    664                                                 mergeListItems( listNode, sibling, !rtl );
     670                                                mergeListItems( listNode, sibling, null, !rtl );
    665671
    666672                                                listNode.remove();
    667673                                                listNode = sibling;
     
    739745        for ( i in dtd.$listItem )
    740746                defaultListHtmlFilterRules.elements[ i ] = getExtendNestedListFilter( true );
    741747
     748        // Check if node is block element that recieves text.
     749        function isTextBlock( node )
     750        {
     751                return node.type == CKEDITOR.NODE_ELEMENT &&
     752                           ( node.getName() in CKEDITOR.dtd.$block ||
     753                                 node.getName() in CKEDITOR.dtd.$listItem ) &&
     754                           CKEDITOR.dtd[ node.getName() ][ '#' ];
     755        }
     756
     757        // Merge the visual line content at the cursor range into the block.
     758        function joinNextLineToCursor( editor, cursor, nextCursor )
     759        {
     760                editor.fire( 'saveSnapshot' );
     761
     762                // Merge with previous block's content.
     763                nextCursor.enlarge( CKEDITOR.ENLARGE_LIST_ITEM_CONTENTS );
     764                var frag = nextCursor.extractContents();
     765
     766                cursor.trim( false, true );
     767
     768                // Kill original bogus;
     769                var block = new CKEDITOR.dom.elementPath( cursor.startContainer ).block;
     770                var bogus = block.getBogus();
     771                bogus && bogus.remove();
     772
     773                // Kill the tail br in extracted.
     774                var last = frag.getLast();
     775                if ( last && last.type == CKEDITOR.NODE_ELEMENT && last.is( 'br' ) )
     776                        last.remove();
     777
     778                // Insert fragment at the range position.
     779                var nextNode = cursor.startContainer.getChild( cursor.startOffset );
     780                if ( nextNode )
     781                        frag.insertBefore( nextNode );
     782                else
     783                        cursor.startContainer.append( frag );
     784
     785
     786                var pathBlock = new CKEDITOR.dom.elementPath( nextCursor.startContainer ).block;
     787                // Migrate the remaining sub list from the list item.
     788                if ( pathBlock )
     789                {
     790                        // Remove the original path block if needed.
     791                        if ( nextCursor.checkStartOfBlock() &&
     792                                 nextCursor.checkEndOfBlock() )
     793                        {
     794                                var parent = pathBlock.getParent();
     795                                pathBlock.remove();
     796
     797                                // Remove the unused container, e.g. div, ul, etc...
     798                                if ( parent && !parent.getFirst( nonEmpty ) )
     799                                        parent.remove();
     800                        }
     801                        else if ( pathBlock.is( 'li' ) )
     802                        {
     803                                var child = pathBlock.getLast( nonEmpty );
     804                                if ( child.type == CKEDITOR.NODE_ELEMENT &&
     805                                         child.getName() in listNodeNames )
     806                                {
     807                                        mergeListItems( child, pathBlock.getParent(), pathBlock );
     808                                        pathBlock.remove();
     809                                }
     810                        }
     811                }
     812
     813                // Make fresh selection.
     814                cursor.select();
     815
     816                editor.fire( 'saveSnapshot' );
     817        }
     818
    742819        CKEDITOR.plugins.add( 'list',
    743820        {
    744821                init : function( editor )
     
    762839                        // Register the state changing handlers.
    763840                        editor.on( 'selectionChange', CKEDITOR.tools.bind( onSelectionChange, numberedListCommand ) );
    764841                        editor.on( 'selectionChange', CKEDITOR.tools.bind( onSelectionChange, bulletedListCommand ) );
     842
     843                        // [IE8] Fix "backspace" after list and "del" at the end of list item. (#8248)
     844                        if ( CKEDITOR.env.ie8Compat )
     845                        {
     846                                editor.on( 'key', function( evt )
     847                                {
     848                                        var key = evt.data.keyCode;
     849
     850                                        // DEl/BACKSPACE
     851                                        if ( editor.mode == 'wysiwyg' && key in { 8 : 1, 46 : 1 } )
     852                                        {
     853                                                var sel = editor.getSelection(),
     854                                                range = sel.getRanges()[ 0 ];
     855
     856                                                if ( !range.collapsed )
     857                                                        return;
     858
     859                                                var isBackspace = key == 8;
     860                                                var body = editor.document.getBody();
     861                                                var walker = new CKEDITOR.dom.walker( range.clone() );
     862                                                walker.evaluator = function( node ) { return nonEmpty( node ) && !blockBogus( node ); };
     863
     864                                                var cursor = range.clone();
     865
     866                                                if ( isBackspace )
     867                                                {
     868                                                        walker.range.setStartAt( body, CKEDITOR.POSITION_AFTER_START );
     869                                                        walker.range.setEnd( range.startContainer, range.startOffset );
     870
     871                                                        var previous = walker.previous();
     872
     873                                                        // Check if cursor collapsed right behind of a list.
     874                                                        if ( previous &&
     875                                                                 previous.type == CKEDITOR.NODE_ELEMENT &&
     876                                                                 previous.getName() in listNodeNames )
     877                                                        {
     878                                                                walker.range.selectNodeContents( previous );
     879                                                                walker.reset();
     880                                                                walker.evaluator = isTextBlock;
     881
     882                                                                // Place cursor at the end of previous block.
     883                                                                cursor.moveToElementEditEnd( walker.lastForward() );
     884                                                                joinNextLineToCursor( editor, cursor, range );
     885                                                                evt.cancel();
     886                                                        }
     887                                                }
     888                                                else
     889                                                {
     890                                                        var li = range.startContainer.getAscendant( 'li', 1 );
     891                                                        if ( li )
     892                                                        {
     893                                                                walker.range.setEndAt( body, CKEDITOR.POSITION_BEFORE_END );
     894
     895                                                                var last = li.getLast( nonEmpty );
     896                                                                var block = last && isTextBlock( last ) ? last : li;
     897
     898                                                                // Indicate cursor at the visual end of an list item.
     899                                                                var isAtEnd = 0;
     900
     901                                                                var next = walker.next();
     902
     903                                                                // When list item contains a sub list.
     904                                                                if ( next && next.type == CKEDITOR.NODE_ELEMENT &&
     905                                                                         next.getName() in listNodeNames
     906                                                                         && next.equals( last ) )
     907                                                                {
     908                                                                        isAtEnd = 1;
     909
     910                                                                        // Move to the first item in sub list.
     911                                                                        next = walker.next();
     912                                                                }
     913                                                                // Right at the end of list item.
     914                                                                else if ( range.checkBoundaryOfElement( block, CKEDITOR.END ) )
     915                                                                        isAtEnd = 1;
     916
     917
     918                                                                if ( isAtEnd && next )
     919                                                                {
     920                                                                        // Put cursor range there.
     921                                                                        var nextLine = range.clone();
     922                                                                        nextLine.moveToElementEditStart( next );
     923
     924                                                                        joinNextLineToCursor( editor, cursor, nextLine );
     925                                                                        evt.cancel();
     926                                                                }
     927                                                        }
     928                                                }
     929                                        }
     930                                } );
     931                        }
    765932                },
    766933
    767934                afterInit : function ( editor )
  • _source/core/dom/range.js

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
     
    380380                };
    381381        }
    382382
     383
     384        var isBogus = CKEDITOR.dom.walker.bogus();
    383385        // Evaluator for CKEDITOR.dom.element::checkBoundaryOfElement, reject any
    384386        // text node and non-empty elements unless it's being bookmark text.
    385         function elementBoundaryEval( node )
     387        function elementBoundaryEval( checkStart )
    386388        {
    387                 // Reject any text node unless it's being bookmark
    388                 // OR it's spaces.
    389                 // Reject any element unless it's being invisible empty. (#3883)
    390                 return node.type == CKEDITOR.NODE_TEXT ?
    391                            !CKEDITOR.tools.trim( node.getText() ) ||
    392                            !!node.getParent().data( 'cke-bookmark' )
    393                            : node.getName() in CKEDITOR.dtd.$removeEmpty;
     389                return function( node )
     390                {
     391                        // Tolerant bogus br when checking at the end of block.
     392                        // Reject any text node unless it's being bookmark
     393                        // OR it's spaces.
     394                        // Reject any element unless it's being invisible empty. (#3883)
     395                        return !checkStart && isBogus( node ) ||
     396                                        ( node.type == CKEDITOR.NODE_TEXT ?
     397                                           !CKEDITOR.tools.trim( node.getText() ) || !!node.getParent().data( 'cke-bookmark' )
     398                                           : node.getName() in CKEDITOR.dtd.$removeEmpty );
     399                };
    394400        }
    395401
    396402        var whitespaceEval = new CKEDITOR.dom.walker.whitespaces(),
     
    18011807                        // Create the walker, which will check if we have anything useful
    18021808                        // in the range.
    18031809                        var walker = new CKEDITOR.dom.walker( walkerRange );
    1804                         walker.evaluator = elementBoundaryEval;
     1810                        walker.evaluator = elementBoundaryEval( checkStart );
    18051811
    18061812                        return walker[ checkStart ? 'checkBackward' : 'checkForward' ]();
    18071813                },
© 2003 – 2019 CKSource – Frederico Knabben. All rights reserved. | Terms of use | Privacy policy