| 742 | // Check if node is block element that recieves text. |
| 743 | function isTextBlock( node ) |
| 744 | { |
| 745 | return node.type == CKEDITOR.NODE_ELEMENT && |
| 746 | ( node.getName() in CKEDITOR.dtd.$block || |
| 747 | node.getName() in CKEDITOR.dtd.$listItem ) && |
| 748 | CKEDITOR.dtd[ node.getName() ][ '#' ]; |
| 749 | } |
| 750 | |
| 751 | // Merge the visual line content at the cursor range into the block. |
| 752 | function joinCursorLineToBlock( block, cursor ) |
| 753 | { |
| 754 | // Place cursor at the end of previous block. |
| 755 | var newCursor = new CKEDITOR.dom.range( cursor.document ); |
| 756 | newCursor.moveToElementEditEnd( block ); |
| 757 | |
| 758 | // Merge with previous block's content. |
| 759 | cursor.enlarge( CKEDITOR.ENLARGE_LIST_ITEM_CONTENTS ); |
| 760 | var frag = cursor.extractContents(); |
| 761 | |
| 762 | // Kill the tail br in extracted. |
| 763 | var last = frag.getLast(); |
| 764 | if ( last && last.type == CKEDITOR.NODE_ELEMENT && |
| 765 | last.is( 'br' ) ) |
| 766 | last.remove(); |
| 767 | |
| 768 | // Kill original bogus; |
| 769 | var bogus = block.getBogus(); |
| 770 | bogus && bogus.remove(); |
| 771 | |
| 772 | block.append( frag ); |
| 773 | |
| 774 | // Remove the original path block if needed. |
| 775 | if ( cursor.checkStartOfBlock() && |
| 776 | cursor.checkEndOfBlock() ) |
| 777 | { |
| 778 | var path = new CKEDITOR.dom.elementPath( cursor.startContainer ); |
| 779 | path.block.remove(); |
| 780 | } |
| 781 | |
| 782 | // Make fresh selection. |
| 783 | newCursor.select(); |
| 784 | |
| 785 | } |
| 786 | |
| 810 | |
| 811 | // [IE8] Fix "backspace" after list and "del" at the end of list item. (#8248) |
| 812 | if ( CKEDITOR.env.ie8Compat ) |
| 813 | { |
| 814 | editor.on( 'key', function( evt ) |
| 815 | { |
| 816 | var key = evt.data.keyCode; |
| 817 | |
| 818 | // DEl/BACKSPACE |
| 819 | if ( editor.mode == 'wysiwyg' && key in { 8 : 1, 46 : 1 } ) |
| 820 | { |
| 821 | var sel = editor.getSelection(), |
| 822 | range = sel.getRanges()[ 0 ]; |
| 823 | |
| 824 | if ( !range.collapsed ) |
| 825 | return; |
| 826 | |
| 827 | var isBackspace = key == 8; |
| 828 | var body = editor.document.getBody(); |
| 829 | var walker = new CKEDITOR.dom.walker( new CKEDITOR.dom.range( editor.document ) ); |
| 830 | walker.evaluator = nonEmpty; |
| 831 | |
| 832 | if ( isBackspace ) |
| 833 | { |
| 834 | walker.range.setStartAt( body, CKEDITOR.POSITION_AFTER_START ); |
| 835 | walker.range.setEnd( range.startContainer, range.startOffset ); |
| 836 | |
| 837 | var previous = walker.previous(); |
| 838 | |
| 839 | // Check if cursor collapsed right behind of a list. |
| 840 | if ( previous && |
| 841 | previous.type == CKEDITOR.NODE_ELEMENT && |
| 842 | previous.getName() in listNodeNames ) |
| 843 | { |
| 844 | walker.range.selectNodeContents( previous ); |
| 845 | walker.reset(); |
| 846 | walker.evaluator = isTextBlock; |
| 847 | joinCursorLineToBlock( walker.lastForward(), range ); |
| 848 | evt.cancel(); |
| 849 | } |
| 850 | } |
| 851 | else |
| 852 | { |
| 853 | var li = range.startContainer.getAscendant( 'li', 1 ); |
| 854 | if ( li ) |
| 855 | { |
| 856 | var block = li.getLast( isTextBlock ) || li; |
| 857 | |
| 858 | // Check cursor at the very end of list item. |
| 859 | if ( range.checkBoundaryOfElement( block, CKEDITOR.END ) ) |
| 860 | { |
| 861 | walker.range.setStartAt( li, CKEDITOR.POSITION_AFTER_END ); |
| 862 | walker.range.setEndAt( body, CKEDITOR.POSITION_BEFORE_END ); |
| 863 | |
| 864 | var next = walker.next(); |
| 865 | |
| 866 | // Check if following the list are inline or text block. |
| 867 | if ( next && next.type == CKEDITOR.NODE_ELEMENT && |
| 868 | ( isTextBlock( next ) || next.getName() in CKEDITOR.dtd.$inline ) ) |
| 869 | { |
| 870 | // Put cursor range there. |
| 871 | range = range.clone(); |
| 872 | range.moveToElementEditStart( next ); |
| 873 | |
| 874 | joinCursorLineToBlock( block, range ); |
| 875 | evt.cancel(); |
| 876 | } |
| 877 | } |
| 878 | } |
| 879 | } |
| 880 | } |
| 881 | } ); |
| 882 | } |