X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=_source%2Fcore%2Fdom%2Frange.js;h=264ee4eff190acd6baa08a3c2e12023fbd05a62f;hb=941b0a9ba4e673e292510d80a5a86806994b8ea6;hp=5b1681f850c41a5118ac98bb844b7e584a1c97fb;hpb=ea7e3453c7b0f023b050aca6d9f83ab372860d91;p=ckeditor.git
diff --git a/_source/core/dom/range.js b/_source/core/dom/range.js
index 5b1681f..264ee4e 100644
--- a/_source/core/dom/range.js
+++ b/_source/core/dom/range.js
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
+Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
For licensing, see LICENSE.html or http://ckeditor.com/license
*/
@@ -278,7 +278,7 @@ CKEDITOR.dom.range = function( document )
if ( CKEDITOR.tools.trim( node.getText() ).length )
return false;
}
- else
+ else if( node.type == CKEDITOR.NODE_ELEMENT )
{
// If there are non-empty inline elements (e.g. ), then we're not
// at the start.
@@ -308,6 +308,15 @@ CKEDITOR.dom.range = function( document )
|| node.getParent().hasAttribute( '_fck_bookmark' );
}
+ var whitespaceEval = new CKEDITOR.dom.walker.whitespaces(),
+ bookmarkEval = new CKEDITOR.dom.walker.bookmark();
+
+ function nonWhitespaceOrBookmarkEval( node )
+ {
+ // Whitespaces and bookmark nodes are to be ignored.
+ return !whitespaceEval( node ) && !bookmarkEval( node );
+ }
+
CKEDITOR.dom.range.prototype =
{
clone : function()
@@ -1183,7 +1192,8 @@ CKEDITOR.dom.range = function( document )
this.setStartAt(
blockBoundary,
!blockBoundary.is( 'br' ) &&
- ( !enlargeable || blockBoundary.contains( enlargeable ) ) ?
+ ( !enlargeable && this.checkStartOfBlock()
+ || enlargeable && blockBoundary.contains( enlargeable ) ) ?
CKEDITOR.POSITION_AFTER_START :
CKEDITOR.POSITION_AFTER_END );
@@ -1208,8 +1218,8 @@ CKEDITOR.dom.range = function( document )
// the document position of it with 'enlargeable' node.
this.setEndAt(
blockBoundary,
- !blockBoundary.is( 'br' ) &&
- ( !enlargeable || blockBoundary.contains( enlargeable ) ) ?
+ ( !enlargeable && this.checkEndOfBlock()
+ || enlargeable && blockBoundary.contains( enlargeable ) ) ?
CKEDITOR.POSITION_BEFORE_END :
CKEDITOR.POSITION_BEFORE_START );
// We must include the
at the end of range if there's
@@ -1457,18 +1467,7 @@ CKEDITOR.dom.range = function( document )
}
else
{
- // Extract the contents of the block from the selection point to the end
- // of its contents.
- this.setEndAt( startBlock, CKEDITOR.POSITION_BEFORE_END );
- var documentFragment = this.extractContents();
-
- // Duplicate the block element after it.
- endBlock = startBlock.clone( false );
-
- // Place the extracted contents into the duplicated block.
- documentFragment.appendTo( endBlock );
- endBlock.insertAfter( startBlock );
- this.moveToPosition( startBlock, CKEDITOR.POSITION_AFTER_END );
+ endBlock = this.splitElement( startBlock );
// In Gecko, the last child node must be a bogus
.
// Note: bogus
added under
or would cause
@@ -1488,6 +1487,33 @@ CKEDITOR.dom.range = function( document )
},
/**
+ * Branch the specified element from the collapsed range position and
+ * place the caret between the two result branches.
+ * Note: The range must be collapsed and been enclosed by this element.
+ * @param {CKEDITOR.dom.element} element
+ * @return {CKEDITOR.dom.element} Root element of the new branch after the split.
+ */
+ splitElement : function( toSplit )
+ {
+ if ( !this.collapsed )
+ return null;
+
+ // Extract the contents of the block from the selection point to the end
+ // of its contents.
+ this.setEndAt( toSplit, CKEDITOR.POSITION_BEFORE_END );
+ var documentFragment = this.extractContents();
+
+ // Duplicate the element after it.
+ var clone = toSplit.clone( false );
+
+ // Place the extracted contents into the duplicated element.
+ documentFragment.appendTo( clone );
+ clone.insertAfter( toSplit );
+ this.moveToPosition( toSplit, CKEDITOR.POSITION_AFTER_END );
+ return clone;
+ },
+
+ /**
* Check whether current range is on the inner edge of the specified element.
* @param {Number} checkType ( CKEDITOR.START | CKEDITOR.END ) The checking side.
* @param {CKEDITOR.dom.element} element The target element to check.
@@ -1579,34 +1605,69 @@ CKEDITOR.dom.range = function( document )
},
/**
- * Moves the range boundaries to the first editing point inside an
+ * Moves the range boundaries to the first/end editing point inside an
* element. For example, in an element tree like
* "<p><b><i></i></b> Text</p>", the start editing point is
* "<p><b><i>^</i></b> Text</p>" (inside <i>).
- * @param {CKEDITOR.dom.element} targetElement The element into which
- * look for the editing spot.
+ * @param {CKEDITOR.dom.element} el The element into which look for the
+ * editing spot.
+ * @param {Boolean} isMoveToEnd Whether move to the end editable position.
*/
- moveToElementEditStart : function( targetElement )
+ moveToElementEditablePosition : function( el, isMoveToEnd )
{
- var editableElement;
+ var isEditable;
- while ( targetElement && targetElement.type == CKEDITOR.NODE_ELEMENT )
+ while ( el && el.type == CKEDITOR.NODE_ELEMENT )
{
- if ( targetElement.isEditable() )
- editableElement = targetElement;
- else if ( editableElement )
- break ; // If we already found an editable element, stop the loop.
+ isEditable = el.isEditable();
+
+ // If an editable element is found, move inside it.
+ if ( isEditable )
+ this.moveToPosition( el, isMoveToEnd ?
+ CKEDITOR.POSITION_BEFORE_END :
+ CKEDITOR.POSITION_AFTER_START );
+ // Stop immediately if we've found a non editable inline element (e.g ).
+ else if ( CKEDITOR.dtd.$inline[ el.getName() ] )
+ {
+ this.moveToPosition( el, isMoveToEnd ?
+ CKEDITOR.POSITION_AFTER_END :
+ CKEDITOR.POSITION_BEFORE_START );
+ return true;
+ }
- targetElement = targetElement.getFirst();
- }
+ // Non-editable non-inline elements are to be bypassed, getting the next one.
+ if ( CKEDITOR.dtd.$empty[ el.getName() ] )
+ el = el[ isMoveToEnd ? 'getPrevious' : 'getNext' ]( nonWhitespaceOrBookmarkEval );
+ else
+ el = el[ isMoveToEnd ? 'getLast' : 'getFirst' ]( nonWhitespaceOrBookmarkEval );
- if ( editableElement )
- {
- this.moveToPosition(editableElement, CKEDITOR.POSITION_AFTER_START);
- return true;
+ // Stop immediately if we've found a text node.
+ if ( el && el.type == CKEDITOR.NODE_TEXT )
+ {
+ this.moveToPosition( el, isMoveToEnd ?
+ CKEDITOR.POSITION_AFTER_END :
+ CKEDITOR.POSITION_BEFORE_START );
+ return true;
+ }
}
- else
- return false;
+
+ return isEditable;
+ },
+
+ /**
+ *@see {CKEDITOR.dom.range.moveToElementEditablePosition}
+ */
+ moveToElementEditStart : function( target )
+ {
+ return this.moveToElementEditablePosition( target );
+ },
+
+ /**
+ *@see {CKEDITOR.dom.range.moveToElementEditablePosition}
+ */
+ moveToElementEditEnd : function( target )
+ {
+ return this.moveToElementEditablePosition( target, true );
},
/**