2685506214ca4d393e86850188c3ffad8e2c7286
2 Copyright (c) 2003-2011, CKSource - Frederico Knabben. All rights reserved.
3 For licensing, see LICENSE.html or http://ckeditor.com/license
9 * Represents a list os CKEDITOR.dom.range objects, which can be easily
10 * iterated sequentially.
12 * @param {CKEDITOR.dom.range|Array} [ranges] The ranges contained on this list.
13 * Note that, if an array of ranges is specified, the range sequence
14 * should match its DOM order. This class will not help to sort them.
16 CKEDITOR
.dom
.rangeList = function( ranges
)
18 if ( ranges
instanceof CKEDITOR
.dom
.rangeList
)
23 else if ( ranges
instanceof CKEDITOR
.dom
.range
)
26 return CKEDITOR
.tools
.extend( ranges
, mixins
);
30 /** @lends CKEDITOR.dom.rangeList.prototype */
33 * Creates an instance of the rangeList iterator, it should be used
34 * only when the ranges processing could be DOM intrusive, which
35 * means it may pollute and break other ranges in this list.
36 * Otherwise, it's enough to just iterate over this array in a for loop.
37 * @returns {CKEDITOR.dom.rangeListIterator}
39 createIterator : function()
42 bookmark
= CKEDITOR
.dom
.walker
.bookmark(),
43 guard = function( node
) { return ! ( node
.is
&& node
.is( 'tr' ) ); },
48 * @lends CKEDITOR.dom.rangeListIterator.prototype
53 * Retrieves the next range in the list.
54 * @param {Boolean} mergeConsequent Whether join two adjacent ranges into single, e.g. consequent table cells.
56 getNextRange : function( mergeConsequent
)
58 current
= current
== undefined ? 0 : current
+ 1;
60 var range
= rangeList
[ current
];
62 // Multiple ranges might be mangled by each other.
63 if ( range
&& rangeList
.length
> 1 )
65 // Bookmarking all other ranges on the first iteration,
66 // the range correctness after it doesn't matter since we'll
67 // restore them before the next iteration.
70 // Make sure bookmark correctness by reverse processing.
71 for ( var i
= rangeList
.length
- 1; i
>= 0; i
-- )
72 bookmarks
.unshift( rangeList
[ i
].createBookmark( true ) );
75 if ( mergeConsequent
)
77 // Figure out how many ranges should be merged.
79 while ( rangeList
[ current
+ mergeCount
+ 1 ] )
81 var doc
= range
.document
,
83 left
= doc
.getById( bookmarks
[ mergeCount
].endNode
),
84 right
= doc
.getById( bookmarks
[ mergeCount
+ 1 ].startNode
),
87 // Check subsequent range.
90 next
= left
.getNextSourceNode( false );
91 if ( !right
.equals( next
) )
93 // This could be yet another bookmark or
94 // walking across block boundaries.
95 if ( bookmark( next
) || ( next
.type
== CKEDITOR
.NODE_ELEMENT
&& next
.isBlockBoundary() ) )
114 range
.moveToBookmark( bookmarks
.shift() );
116 // Merge ranges finally after moving to bookmarks.
117 while( mergeCount
-- )
119 next
= rangeList
[ ++current
];
120 next
.moveToBookmark( bookmarks
.shift() );
121 range
.setEnd( next
.endContainer
, next
.endOffset
);
130 createBookmarks : function( serializable
)
132 var retval
= [], bookmark
;
133 for ( var i
= 0; i
< this.length
; i
++ )
135 retval
.push( bookmark
= this[ i
].createBookmark( serializable
, true) );
137 // Updating the container & offset values for ranges
138 // that have been touched.
139 for ( var j
= i
+ 1; j
< this.length
; j
++ )
141 this[ j
] = updateDirtyRange( bookmark
, this[ j
] );
142 this[ j
] = updateDirtyRange( bookmark
, this[ j
], true );
148 createBookmarks2 : function( normalized
)
152 for ( var i
= 0 ; i
< this.length
; i
++ )
153 bookmarks
.push( this[ i
].createBookmark2( normalized
) );
159 * Move each range in the list to the position specified by a list of bookmarks.
160 * @param {Array} bookmarks The list of bookmarks, each one matching a range in the list.
162 moveToBookmarks : function( bookmarks
)
164 for ( var i
= 0 ; i
< this.length
; i
++ )
165 this[ i
].moveToBookmark( bookmarks
[ i
] );
169 // Update the specified range which has been mangled by previous insertion of
170 // range bookmark nodes.(#3256)
171 function updateDirtyRange( bookmark
, dirtyRange
, checkEnd
)
173 var serializable
= bookmark
.serializable
,
174 container
= dirtyRange
[ checkEnd
? 'endContainer' : 'startContainer' ],
175 offset
= checkEnd
? 'endOffset' : 'startOffset';
177 var bookmarkStart
= serializable
?
178 dirtyRange
.document
.getById( bookmark
.startNode
)
179 : bookmark
.startNode
;
181 var bookmarkEnd
= serializable
?
182 dirtyRange
.document
.getById( bookmark
.endNode
)
185 if ( container
.equals( bookmarkStart
.getPrevious() ) )
187 dirtyRange
.startOffset
= dirtyRange
.startOffset
188 - container
.getLength()
189 - bookmarkEnd
.getPrevious().getLength();
190 container
= bookmarkEnd
.getNext();
192 else if ( container
.equals( bookmarkEnd
.getPrevious() ) )
194 dirtyRange
.startOffset
= dirtyRange
.startOffset
- container
.getLength();
195 container
= bookmarkEnd
.getNext();
198 container
.equals( bookmarkStart
.getParent() ) && dirtyRange
[ offset
]++;
199 container
.equals( bookmarkEnd
.getParent() ) && dirtyRange
[ offset
]++;
201 // Update and return this range.
202 dirtyRange
[ checkEnd
? 'endContainer' : 'startContainer' ] = container
;
208 * (Virtual Class) Do not call this constructor. This class is not really part
209 * of the API. It just describes the return type of {@link CKEDITOR.dom.rangeList#createIterator}.
210 * @name CKEDITOR.dom.rangeListIterator