Changeset 7439
- Timestamp:
- 03/30/12 12:10:54 (14 months ago)
- Location:
- CKEditor/trunk
- Files:
-
- 4 edited
-
CHANGES.html (modified) (1 diff)
-
_source/core/dom/range.js (modified) (2 diffs)
-
_source/core/dom/walker.js (modified) (1 diff)
-
_source/plugins/list/plugin.js (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
-
CKEditor/trunk/CHANGES.html
r7437 r7439 85 85 <li><a href="http://dev.ckeditor.com/ticket/8835">#8835</a> : Removing the right margin on IE<8 to avoid mouse click confusion.</li> 86 86 <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> 87 88 </ul> 88 89 <h3> -
CKEditor/trunk/_source/core/dom/range.js
r7406 r7439 381 381 } 382 382 383 384 var isBogus = CKEDITOR.dom.walker.bogus(); 383 385 // Evaluator for CKEDITOR.dom.element::checkBoundaryOfElement, reject any 384 386 // text node and non-empty elements unless it's being bookmark text. 385 function elementBoundaryEval( node)387 function elementBoundaryEval( checkStart ) 386 388 { 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 }; 394 400 } 395 401 … … 1802 1808 // in the range. 1803 1809 var walker = new CKEDITOR.dom.walker( walkerRange ); 1804 walker.evaluator = elementBoundaryEval ;1810 walker.evaluator = elementBoundaryEval( checkStart ); 1805 1811 1806 1812 return walker[ checkStart ? 'checkBackward' : 'checkForward' ](); -
CKEditor/trunk/_source/core/dom/walker.js
r7397 r7439 447 447 }; 448 448 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 449 468 var tailNbspRegex = /^[\t\r\n ]*(?: |\xa0)$/, 450 469 isWhitespaces = CKEDITOR.dom.walker.whitespaces(), -
CKEditor/trunk/_source/plugins/list/plugin.js
r7428 r7439 15 15 var whitespaces = CKEDITOR.dom.walker.whitespaces(), 16 16 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(); 18 19 19 20 function cleanUpDirection( element ) … … 496 497 var elementType = CKEDITOR.dom.walker.nodeType( CKEDITOR.NODE_ELEMENT ); 497 498 // Merge list items with direction preserved. (#7448) 498 function mergeListItems( from, into, toHead )499 function mergeListItems( from, into, refNode, toHead ) 499 500 { 500 501 var child, itemDir; … … 503 504 if ( ( itemDir = child.getDirection( 1 ) ) !== into.getDirection( 1 ) ) 504 505 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 ); 506 512 } 507 513 } … … 662 668 { 663 669 // Move children order by merge direction.(#3820) 664 mergeListItems( listNode, sibling, !rtl );670 mergeListItems( listNode, sibling, null, !rtl ); 665 671 666 672 listNode.remove(); … … 740 746 defaultListHtmlFilterRules.elements[ i ] = getExtendNestedListFilter( true ); 741 747 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 742 838 CKEDITOR.plugins.add( 'list', 743 839 { … … 763 859 editor.on( 'selectionChange', CKEDITOR.tools.bind( onSelectionChange, numberedListCommand ) ); 764 860 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 } 765 951 }, 766 952
Note: See TracChangeset
for help on using the changeset viewer.
