| | 697 | |
| | 698 | // Registering keydown delete/backspace key handling logic. |
| | 699 | editor.on( 'contentDom', function() |
| | 700 | { |
| | 701 | editor.document.on( 'keydown', function( evt ) |
| | 702 | { |
| | 703 | var keyCode = evt.data.getKeystroke(); |
| | 704 | |
| | 705 | // Backspace or Delete. |
| | 706 | if ( keyCode in { 8 : 1, 46 : 1 } ) |
| | 707 | { |
| | 708 | var range = editor.getSelection().getRanges()[ 0 ], |
| | 709 | block = new CKEDITOR.dom.elementPath( range.startContainer ).block, |
| | 710 | li; |
| | 711 | |
| | 712 | if ( range.collapsed && ( li = block.getAscendant( 'li', true ) ) ) |
| | 713 | { |
| | 714 | function moveListItem( source, target ) |
| | 715 | { |
| | 716 | editor.fire( 'saveSnapshot' ); |
| | 717 | |
| | 718 | var sourceLast = source.getLast(), |
| | 719 | targetLast = target.getLast(); |
| | 720 | |
| | 721 | // In Gecko, the last child node is <br>. |
| | 722 | if ( CKEDITOR.env.gecko ) |
| | 723 | { |
| | 724 | sourceLast && sourceLast.is && sourceLast.is( 'br' ) && sourceLast.remove(); |
| | 725 | targetLast && targetLast.is && targetLast.is( 'br' ) && targetLast.remove(); |
| | 726 | } |
| | 727 | |
| | 728 | if ( target.is && target.is( 'body' ) ) |
| | 729 | { |
| | 730 | source.moveChildren( target, true ); |
| | 731 | range.moveToPosition( target, CKEDITOR.POSITION_AFTER_START ); |
| | 732 | } |
| | 733 | else |
| | 734 | { |
| | 735 | var innerTarget = |
| | 736 | targetLast && targetLast.is && targetLast.is( 'p', 'div' ) ? |
| | 737 | targetLast : target; |
| | 738 | |
| | 739 | range.moveToElementEditEnd( innerTarget ); |
| | 740 | |
| | 741 | var sourceFirstChild = source.getChild( 0 ); |
| | 742 | if ( source.getChildCount() == 1 ) |
| | 743 | { |
| | 744 | var innerSource = |
| | 745 | sourceFirstChild.is && sourceFirstChild.is( 'p', 'div' ) ? |
| | 746 | sourceFirstChild : source; |
| | 747 | |
| | 748 | innerSource.moveChildren( innerTarget ); |
| | 749 | } |
| | 750 | else if ( source.getChildCount() > 1 ) |
| | 751 | { |
| | 752 | var innerFirst = |
| | 753 | sourceFirstChild.is && sourceFirstChild.is( 'p', 'div' ) ? |
| | 754 | sourceFirstChild.getFirst() : sourceFirstChild; |
| | 755 | |
| | 756 | innerTarget.append( innerFirst ); |
| | 757 | sourceFirstChild.remove(); |
| | 758 | source.moveChildren( target ); |
| | 759 | } |
| | 760 | } |
| | 761 | |
| | 762 | source.remove(); |
| | 763 | range.select(); |
| | 764 | evt.data.preventDefault(); |
| | 765 | } |
| | 766 | |
| | 767 | // Backspace |
| | 768 | if ( keyCode == 8 && range.checkStartOfBlock() && !block.getPrevious() ) |
| | 769 | { |
| | 770 | var previous; |
| | 771 | |
| | 772 | // Previous element is item of the same list. |
| | 773 | if ( ( previous = li.getPrevious() ) && previous.is && previous.is( 'li' ) ) |
| | 774 | { |
| | 775 | moveListItem( li, previous ); |
| | 776 | } |
| | 777 | else |
| | 778 | { |
| | 779 | var currentList = li.getParent(); |
| | 780 | |
| | 781 | // Previous element doesn't exist (curent list item is first item in editor area). |
| | 782 | if ( !currentList.getPrevious() ) |
| | 783 | { |
| | 784 | moveListItem( li, range.document.getBody() ); |
| | 785 | } |
| | 786 | // Previous element is some block before list. |
| | 787 | else |
| | 788 | { |
| | 789 | range.setStartAt( currentList.getParent(), CKEDITOR.POSITION_AFTER_START ); |
| | 790 | range.setEndAt( currentList, CKEDITOR.POSITION_AFTER_START ); |
| | 791 | |
| | 792 | var walker = new CKEDITOR.dom.walker( range ); |
| | 793 | while ( previous = walker.next() ) |
| | 794 | { |
| | 795 | if ( previous.getNext() && previous.getNext().equals( currentList ) ) |
| | 796 | { |
| | 797 | moveListItem( li, previous ); |
| | 798 | break; |
| | 799 | } |
| | 800 | } |
| | 801 | } |
| | 802 | |
| | 803 | if ( currentList.getChildCount() == 0 ) |
| | 804 | currentList.remove(); |
| | 805 | } |
| | 806 | } |
| | 807 | // Delete |
| | 808 | else if ( keyCode == 46 ) |
| | 809 | { |
| | 810 | var sublist = li.getFirst( function( node ){ return node.is && node.is( 'ol', 'ul' ); } ); |
| | 811 | |
| | 812 | // Check if cursor (range) is set in the end of current list item. |
| | 813 | // If list item doesn't contain any sublist we can use range::checkEndOfBlock() function. |
| | 814 | // If list item contains sublist, we have to use walker to find if the next element is sublist. |
| | 815 | if ( !range.checkEndOfBlock() ) |
| | 816 | { |
| | 817 | if ( sublist ) |
| | 818 | { |
| | 819 | var walkerRange = range.clone(); |
| | 820 | walkerRange.setEndAt( sublist, CKEDITOR.POSITION_AFTER_START ); |
| | 821 | |
| | 822 | var walker = new CKEDITOR.dom.walker( walkerRange ); |
| | 823 | walker.evaluator = function( node ) |
| | 824 | { |
| | 825 | if ( CKEDITOR.env.gecko && node.is && node.is( 'br' ) && node.getNext().is && node.getNext().is( 'ul' ) ) |
| | 826 | return false; |
| | 827 | } |
| | 828 | |
| | 829 | if ( !walker.next().equals( sublist ) ) |
| | 830 | return; |
| | 831 | } |
| | 832 | else |
| | 833 | return; |
| | 834 | } |
| | 835 | |
| | 836 | var next; |
| | 837 | |
| | 838 | // Next element is item of the same list. |
| | 839 | if ( !sublist && ( next = li.getNext() ) ) |
| | 840 | { |
| | 841 | moveListItem( next, li ); |
| | 842 | } |
| | 843 | // Next element is item of sublist |
| | 844 | else if ( sublist && ( next = sublist.getFirst( function( node ) { return node.is( 'li' ) } ) ) ) |
| | 845 | { |
| | 846 | range.setStartAt( li, CKEDITOR.POSITION_AFTER_START ); |
| | 847 | |
| | 848 | var walker = new CKEDITOR.dom.walker( range ), |
| | 849 | currentBlock; |
| | 850 | |
| | 851 | while ( currentBlock = walker.next() ) |
| | 852 | { |
| | 853 | var item = currentBlock.getNext(); |
| | 854 | |
| | 855 | if ( CKEDITOR.env.gecko && item.is && item.is( 'br' ) && item.getNext() && item.getNext().equals( sublist ) || |
| | 856 | item && item.equals( sublist ) ) |
| | 857 | { |
| | 858 | moveListItem( next, currentBlock ); |
| | 859 | break; |
| | 860 | } |
| | 861 | } |
| | 862 | |
| | 863 | if ( sublist.getChildCount() == 0 ) |
| | 864 | sublist.remove(); |
| | 865 | } |
| | 866 | } |
| | 867 | } |
| | 868 | } |
| | 869 | }); |
| | 870 | }); |