docs: function() {
  			var startNode = this.startContainer,
  				endNode = this.endContainer,
  				startOffset = this.startOffset,
  				endOffset = this.endOffset,
  				childCount;
  
  			if ( startNode.type == CKEDITOR.NODE_ELEMENT ) {
  				childCount = startNode.getChildCount();
  				if ( childCount > startOffset )
  					startNode = startNode.getChild( startOffset );
  				else if ( childCount < 1 )
  					startNode = startNode.getPreviousSourceNode();
  				else // startOffset > childCount but childCount is not 0
  				{
  					// Try to take the node just after the current position.
  					startNode = startNode.$;
  					while ( startNode.lastChild )
  						startNode = startNode.lastChild;
  					startNode = new CKEDITOR.dom.node( startNode );
  
  					// Normally we should take the next node in DFS order. But it
  					// is also possible that we've already reached the end of
  					// document.
  					startNode = startNode.getNextSourceNode() || startNode;
  				}
  			}
  			if ( endNode.type == CKEDITOR.NODE_ELEMENT ) {
  				childCount = endNode.getChildCount();
  				if ( childCount > endOffset )
  					endNode = endNode.getChild( endOffset ).getPreviousSourceNode( true );
  				else if ( childCount < 1 )
  					endNode = endNode.getPreviousSourceNode();
  				else // endOffset > childCount but childCount is not 0
  				{
  					// Try to take the node just before the current position.
  					endNode = endNode.$;
  					while ( endNode.lastChild )
  						endNode = endNode.lastChild;
  					endNode = new CKEDITOR.dom.node( endNode );
  				}
  			}
  
  			// Sometimes the endNode will come right before startNode for collapsed
  			// ranges. Fix it. (#3780)
  			if ( startNode.getPosition( endNode ) & CKEDITOR.POSITION_FOLLOWING )
  				startNode = endNode;
  
  			return { startNode: startNode, endNode: endNode };
  		}