Changeset 7439


Ignore:
Timestamp:
03/30/12 12:10:54 (2 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 – 2012 CKSource – Frederico Knabben. All rights reserved. | Terms of use | Privacy policy