Ticket #8248: 8248_5.patch

File 8248_5.patch, 9.9 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 currentPath = new CKEDITOR.dom.elementPath( cursor.startContainer );
     770                var currentLi = currentPath.lastElement.getAscendant( 'li', 1 );
     771
     772                var bogus = currentPath.block.getBogus();
     773                bogus && bogus.remove();
     774
     775                // Kill the tail br in extracted.
     776                var last = frag.getLast();
     777                if ( last && last.type == CKEDITOR.NODE_ELEMENT && last.is( 'br' ) )
     778                        last.remove();
     779
     780                // Insert fragment at the range position.
     781                var nextNode = cursor.startContainer.getChild( cursor.startOffset );
     782                if ( nextNode )
     783                        frag.insertBefore( nextNode );
     784                else
     785                        cursor.startContainer.append( frag );
     786
     787                var nextPath = new CKEDITOR.dom.elementPath( nextCursor.startContainer );
     788                var nextLi = nextCursor.startContainer.getAscendant( 'li', 1 );
     789
     790                // Move the sub list nested in the next list item.
     791                if ( nextLi )
     792                {
     793                        var sublist = getSubList( nextLi );
     794                        if ( sublist )
     795                        {
     796                                // If next line is in the sub list of the current list item.
     797                                if ( currentLi.contains( nextLi ) )
     798                                {
     799                                        mergeListItems( sublist, nextLi.getParent(), nextLi );
     800                                        sublist.remove();
     801                                }
     802                                // Migrate the sub list to current list item.
     803                                else
     804                                        currentLi.append( sublist );
     805                        }
     806                }
     807
     808
     809                if ( nextCursor.checkStartOfBlock() &&
     810                         nextCursor.checkEndOfBlock() )
     811                {
     812                        var nextBlock = nextPath.block,
     813                                parentBlock = nextBlock.getParent();
     814
     815                        nextBlock.remove();
     816
     817                        // Remove if the path block container is now empty, e.g. li.
     818                        if ( parentBlock &&
     819                                 !parentBlock.getFirst( nonEmpty ) &&
     820                                 !parentBlock.equals( nextPath.blockLimit ) )
     821                        {
     822                                parentBlock.remove();
     823                        }
     824                }
     825
     826                // Make fresh selection.
     827                cursor.select();
     828
     829                editor.fire( 'saveSnapshot' );
     830        }
     831
     832        function getSubList( li )
     833        {
     834                var last = li.getLast( nonEmpty );
     835                return last && last.type == CKEDITOR.NODE_ELEMENT && last.getName() in listNodeNames ? last : null;
     836        }
     837
    742838        CKEDITOR.plugins.add( 'list',
    743839        {
    744840                init : function( editor )
     
    762858                        // Register the state changing handlers.
    763859                        editor.on( 'selectionChange', CKEDITOR.tools.bind( onSelectionChange, numberedListCommand ) );
    764860                        editor.on( 'selectionChange', CKEDITOR.tools.bind( onSelectionChange, bulletedListCommand ) );
     861
     862                        // [IE8] Fix "backspace" after list and "del" at the end of list item. (#8248)
     863//                      if ( CKEDITOR.env.ie8Compat )
     864                        if ( 1 )
     865                        {
     866                                editor.on( 'key', function( evt )
     867                                {
     868                                        var key = evt.data.keyCode;
     869
     870                                        // DEl/BACKSPACE
     871                                        if ( editor.mode == 'wysiwyg' && key in { 8 : 1, 46 : 1 } )
     872                                        {
     873                                                var sel = editor.getSelection(),
     874                                                range = sel.getRanges()[ 0 ];
     875
     876                                                if ( !range.collapsed )
     877                                                        return;
     878
     879                                                var isBackspace = key == 8;
     880                                                var body = editor.document.getBody();
     881                                                var walker = new CKEDITOR.dom.walker( range.clone() );
     882                                                walker.evaluator = function( node ) { return nonEmpty( node ) && !blockBogus( node ); };
     883
     884                                                var cursor = range.clone();
     885
     886                                                if ( isBackspace )
     887                                                {
     888                                                        walker.range.setStartAt( body, CKEDITOR.POSITION_AFTER_START );
     889                                                        walker.range.setEnd( range.startContainer, range.startOffset );
     890
     891                                                        var previous = walker.previous();
     892
     893                                                        // Check if cursor collapsed right behind of a list.
     894                                                        if ( previous &&
     895                                                                 previous.type == CKEDITOR.NODE_ELEMENT &&
     896                                                                 previous.getName() in listNodeNames )
     897                                                        {
     898                                                                walker.range.selectNodeContents( previous );
     899                                                                walker.reset();
     900                                                                walker.evaluator = isTextBlock;
     901
     902                                                                // Place cursor at the end of previous block.
     903                                                                cursor.moveToElementEditEnd( walker.lastForward() );
     904                                                                joinNextLineToCursor( editor, cursor, range );
     905                                                                evt.cancel();
     906                                                        }
     907                                                }
     908                                                else
     909                                                {
     910                                                        var li = range.startContainer.getAscendant( 'li', 1 );
     911                                                        if ( li )
     912                                                        {
     913                                                                walker.range.setEndAt( body, CKEDITOR.POSITION_BEFORE_END );
     914
     915                                                                var last = li.getLast( nonEmpty );
     916                                                                var block = last && isTextBlock( last ) ? last : li;
     917
     918                                                                // Indicate cursor at the visual end of an list item.
     919                                                                var isAtEnd = 0;
     920
     921                                                                var next = walker.next();
     922
     923                                                                // When list item contains a sub list.
     924                                                                if ( next && next.type == CKEDITOR.NODE_ELEMENT &&
     925                                                                         next.getName() in listNodeNames
     926                                                                         && next.equals( last ) )
     927                                                                {
     928                                                                        isAtEnd = 1;
     929
     930                                                                        // Move to the first item in sub list.
     931                                                                        next = walker.next();
     932                                                                }
     933                                                                // Right at the end of list item.
     934                                                                else if ( range.checkBoundaryOfElement( block, CKEDITOR.END ) )
     935                                                                        isAtEnd = 1;
     936
     937
     938                                                                if ( isAtEnd && next )
     939                                                                {
     940                                                                        // Put cursor range there.
     941                                                                        var nextLine = range.clone();
     942                                                                        nextLine.moveToElementEditStart( next );
     943
     944                                                                        joinNextLineToCursor( editor, cursor, nextLine );
     945                                                                        evt.cancel();
     946                                                                }
     947                                                        }
     948                                                }
     949                                        }
     950                                } );
     951                        }
    765952                },
    766953
    767954                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