Changeset 7439


Ignore:
Timestamp:
03/30/12 12:10:54 (3 years ago)
Author:
garry.yao
Message:

#8248: Fixing the del/backspace behavior in ie8.

Location:
CKEditor/trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • CKEditor/trunk/CHANGES.html

    r7437 r7439  
    8585                <li><a href="http://dev.ckeditor.com/ticket/8835">#8835</a> : Removing the right margin on IE&lt;8 to avoid mouse click confusion.</li>
    8686                <li><a href="http://dev.ckeditor.com/ticket/8400">#8400</a> : [IE] Fix script error when closing cellProperties dialog if table cell text is selected.</li>
     87                <li><a href="http://dev.ckeditor.com/ticket/8248">#8248</a> : [IE8] Fix BACKSPACE/DEL keys when working at the start/end of list items.</li>
    8788        </ul>
    8889        <h3>
  • CKEditor/trunk/_source/core/dom/range.js

    r7406 r7439  
    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
     
    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' ]();
  • CKEditor/trunk/_source/core/dom/walker.js

    r7397 r7439  
    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(),
  • CKEditor/trunk/_source/plugins/list/plugin.js

    r7428 r7439  
    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 )
     
    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;
     
    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        }
     
    662668                                        {
    663669                                                // Move children order by merge direction.(#3820)
    664                                                 mergeListItems( listNode, sibling, !rtl );
     670                                                mergeListItems( listNode, sibling, null, !rtl );
    665671
    666672                                                listNode.remove();
     
    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        {
     
    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                        {
     865                                editor.on( 'key', function( evt )
     866                                {
     867                                        var key = evt.data.keyCode;
     868
     869                                        // DEl/BACKSPACE
     870                                        if ( editor.mode == 'wysiwyg' && key in { 8 : 1, 46 : 1 } )
     871                                        {
     872                                                var sel = editor.getSelection(),
     873                                                range = sel.getRanges()[ 0 ];
     874
     875                                                if ( !range.collapsed )
     876                                                        return;
     877
     878                                                var isBackspace = key == 8;
     879                                                var body = editor.document.getBody();
     880                                                var walker = new CKEDITOR.dom.walker( range.clone() );
     881                                                walker.evaluator = function( node ) { return nonEmpty( node ) && !blockBogus( node ); };
     882
     883                                                var cursor = range.clone();
     884
     885                                                if ( isBackspace )
     886                                                {
     887                                                        walker.range.setStartAt( body, CKEDITOR.POSITION_AFTER_START );
     888                                                        walker.range.setEnd( range.startContainer, range.startOffset );
     889
     890                                                        var previous = walker.previous();
     891
     892                                                        // Check if cursor collapsed right behind of a list.
     893                                                        if ( previous &&
     894                                                                 previous.type == CKEDITOR.NODE_ELEMENT &&
     895                                                                 previous.getName() in listNodeNames )
     896                                                        {
     897                                                                walker.range.selectNodeContents( previous );
     898                                                                walker.reset();
     899                                                                walker.evaluator = isTextBlock;
     900
     901                                                                // Place cursor at the end of previous block.
     902                                                                cursor.moveToElementEditEnd( walker.lastForward() );
     903                                                                joinNextLineToCursor( editor, cursor, range );
     904                                                                evt.cancel();
     905                                                        }
     906                                                }
     907                                                else
     908                                                {
     909                                                        var li = range.startContainer.getAscendant( 'li', 1 );
     910                                                        if ( li )
     911                                                        {
     912                                                                walker.range.setEndAt( body, CKEDITOR.POSITION_BEFORE_END );
     913
     914                                                                var last = li.getLast( nonEmpty );
     915                                                                var block = last && isTextBlock( last ) ? last : li;
     916
     917                                                                // Indicate cursor at the visual end of an list item.
     918                                                                var isAtEnd = 0;
     919
     920                                                                var next = walker.next();
     921
     922                                                                // When list item contains a sub list.
     923                                                                if ( next && next.type == CKEDITOR.NODE_ELEMENT &&
     924                                                                         next.getName() in listNodeNames
     925                                                                         && next.equals( last ) )
     926                                                                {
     927                                                                        isAtEnd = 1;
     928
     929                                                                        // Move to the first item in sub list.
     930                                                                        next = walker.next();
     931                                                                }
     932                                                                // Right at the end of list item.
     933                                                                else if ( range.checkBoundaryOfElement( block, CKEDITOR.END ) )
     934                                                                        isAtEnd = 1;
     935
     936
     937                                                                if ( isAtEnd && next )
     938                                                                {
     939                                                                        // Put cursor range there.
     940                                                                        var nextLine = range.clone();
     941                                                                        nextLine.moveToElementEditStart( next );
     942
     943                                                                        joinNextLineToCursor( editor, cursor, nextLine );
     944                                                                        evt.cancel();
     945                                                                }
     946                                                        }
     947                                                }
     948                                        }
     949                                } );
     950                        }
    765951                },
    766952
Note: See TracChangeset for help on using the changeset viewer.
© 2003 – 2015 CKSource – Frederico Knabben. All rights reserved. | Terms of use | Privacy policy