diff options
Diffstat (limited to 'sources/core/dom/range.js')
-rw-r--r-- | sources/core/dom/range.js | 67 |
1 files changed, 57 insertions, 10 deletions
diff --git a/sources/core/dom/range.js b/sources/core/dom/range.js index fe75c550..b5e87363 100644 --- a/sources/core/dom/range.js +++ b/sources/core/dom/range.js | |||
@@ -1,5 +1,5 @@ | |||
1 | /** | 1 | /** |
2 | * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. | 2 | * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved. |
3 | * For licensing, see LICENSE.md or http://ckeditor.com/license | 3 | * For licensing, see LICENSE.md or http://ckeditor.com/license |
4 | */ | 4 | */ |
5 | 5 | ||
@@ -804,12 +804,12 @@ CKEDITOR.dom.range = function( root ) { | |||
804 | var sum = 0; | 804 | var sum = 0; |
805 | 805 | ||
806 | while ( ( node = node.getPrevious() ) && node.type == CKEDITOR.NODE_TEXT ) | 806 | while ( ( node = node.getPrevious() ) && node.type == CKEDITOR.NODE_TEXT ) |
807 | sum += node.getLength(); | 807 | sum += node.getText().replace( CKEDITOR.dom.selection.FILLING_CHAR_SEQUENCE, '' ).length; |
808 | 808 | ||
809 | return sum; | 809 | return sum; |
810 | } | 810 | } |
811 | 811 | ||
812 | function normalize( limit ) { | 812 | function normalizeTextNodes( limit ) { |
813 | var container = limit.container, | 813 | var container = limit.container, |
814 | offset = limit.offset; | 814 | offset = limit.offset; |
815 | 815 | ||
@@ -820,11 +820,13 @@ CKEDITOR.dom.range = function( root ) { | |||
820 | offset = container.getLength(); | 820 | offset = container.getLength(); |
821 | } | 821 | } |
822 | 822 | ||
823 | // Now, if limit is anchored in element and has at least two nodes before it, | 823 | // Now, if limit is anchored in element and has at least one node before it, |
824 | // it may happen that some of them will be merged. Normalize the offset | 824 | // it may happen that some of them will be merged. Normalize the offset |
825 | // by setting it to normalized index of its preceding node. | 825 | // by setting it to normalized index of its preceding, safe node. |
826 | if ( container.type == CKEDITOR.NODE_ELEMENT && offset > 1 ) | 826 | // (safe == one for which getIndex(true) does not return -1, so one which won't disappear). |
827 | offset = container.getChild( offset - 1 ).getIndex( true ) + 1; | 827 | if ( container.type == CKEDITOR.NODE_ELEMENT && offset > 0 ) { |
828 | offset = getPrecedingSafeNodeIndex( container, offset ) + 1; | ||
829 | } | ||
828 | 830 | ||
829 | // The last step - fix the offset inside text node by adding | 831 | // The last step - fix the offset inside text node by adding |
830 | // lengths of preceding text nodes which will be merged with container. | 832 | // lengths of preceding text nodes which will be merged with container. |
@@ -870,6 +872,48 @@ CKEDITOR.dom.range = function( root ) { | |||
870 | limit.offset = offset; | 872 | limit.offset = offset; |
871 | } | 873 | } |
872 | 874 | ||
875 | function normalizeFCSeq( limit, root ) { | ||
876 | var fcseq = root.getCustomData( 'cke-fillingChar' ); | ||
877 | |||
878 | if ( !fcseq ) { | ||
879 | return; | ||
880 | } | ||
881 | |||
882 | var container = limit.container; | ||
883 | |||
884 | if ( fcseq.equals( container ) ) { | ||
885 | limit.offset -= CKEDITOR.dom.selection.FILLING_CHAR_SEQUENCE.length; | ||
886 | |||
887 | // == 0 handles case when limit was at the end of FCS. | ||
888 | // < 0 handles all cases where limit was somewhere in the middle or at the beginning. | ||
889 | // > 0 (the "else" case) means cases where there are some more characters in the FCS node (FCSabc^def). | ||
890 | if ( limit.offset <= 0 ) { | ||
891 | limit.offset = container.getIndex(); | ||
892 | limit.container = container.getParent(); | ||
893 | } | ||
894 | return; | ||
895 | } | ||
896 | |||
897 | // And here goes the funny part - all other cases are handled inside node.getAddress() and getIndex() thanks to | ||
898 | // node.getIndex() being aware of FCS (handling it as an empty node). | ||
899 | } | ||
900 | |||
901 | // Finds a normalized index of a safe node preceding this one. | ||
902 | // Safe == one that will not disappear, so one for which getIndex( true ) does not return -1. | ||
903 | // Return -1 if there's no safe preceding node. | ||
904 | function getPrecedingSafeNodeIndex( container, offset ) { | ||
905 | var index; | ||
906 | |||
907 | while ( offset-- ) { | ||
908 | index = container.getChild( offset ).getIndex( true ); | ||
909 | |||
910 | if ( index >= 0 ) | ||
911 | return index; | ||
912 | } | ||
913 | |||
914 | return -1; | ||
915 | } | ||
916 | |||
873 | return function( normalized ) { | 917 | return function( normalized ) { |
874 | var collapsed = this.collapsed, | 918 | var collapsed = this.collapsed, |
875 | bmStart = { | 919 | bmStart = { |
@@ -882,10 +926,13 @@ CKEDITOR.dom.range = function( root ) { | |||
882 | }; | 926 | }; |
883 | 927 | ||
884 | if ( normalized ) { | 928 | if ( normalized ) { |
885 | normalize( bmStart ); | 929 | normalizeTextNodes( bmStart ); |
930 | normalizeFCSeq( bmStart, this.root ); | ||
886 | 931 | ||
887 | if ( !collapsed ) | 932 | if ( !collapsed ) { |
888 | normalize( bmEnd ); | 933 | normalizeTextNodes( bmEnd ); |
934 | normalizeFCSeq( bmEnd, this.root ); | ||
935 | } | ||
889 | } | 936 | } |
890 | 937 | ||
891 | return { | 938 | return { |