X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=_source%2Fcore%2Fdom%2Frange.js;h=3d8b10f0f31a50b2ff1c9af69466f228d25358aa;hb=055b6b0792ce7dc53d47af606b367c04b927c2ab;hp=127f7aaba39ce553c0961f31b471c82436c47d2f;hpb=e7789c1ad838194d45eeee6ac2eb6e55f5cf35a1;p=ckeditor.git
diff --git a/_source/core/dom/range.js b/_source/core/dom/range.js
index 127f7aa..3d8b10f 100644
--- a/_source/core/dom/range.js
+++ b/_source/core/dom/range.js
@@ -697,7 +697,7 @@ CKEDITOR.dom.range = function( document )
},
/**
- * Move the range out of bookmark nodes if they're been the container.
+ * Move the range out of bookmark nodes if they'd been the container.
*/
optimizeBookmark: function()
{
@@ -1166,13 +1166,13 @@ CKEDITOR.dom.range = function( document )
var walker = new CKEDITOR.dom.walker( walkerRange ),
blockBoundary, // The node on which the enlarging should stop.
- tailBr, //
- defaultGuard = CKEDITOR.dom.walker.blockBoundary(
+ tailBr, // In case BR as block boundary.
+ notBlockBoundary = CKEDITOR.dom.walker.blockBoundary(
( unit == CKEDITOR.ENLARGE_LIST_ITEM_CONTENTS ) ? { br : 1 } : null ),
// Record the encountered 'blockBoundary' for later use.
boundaryGuard = function( node )
{
- var retval = defaultGuard( node );
+ var retval = notBlockBoundary( node );
if ( !retval )
blockBoundary = node;
return retval;
@@ -1193,8 +1193,9 @@ CKEDITOR.dom.range = function( document )
// It's the body which stop the enlarging if no block boundary found.
blockBoundary = blockBoundary || body;
- // Start the range at different position by comparing
- // the document position of it with 'enlargeable' node.
+ // Start the range either after the end of found block (
...
[text)
+ // or at the start of block ([text...), by comparing the document position
+ // with 'enlargeable' node.
this.setStartAt(
blockBoundary,
!blockBoundary.is( 'br' ) &&
@@ -1220,8 +1221,8 @@ CKEDITOR.dom.range = function( document )
// It's the body which stop the enlarging if no block boundary found.
blockBoundary = blockBoundary || body;
- // Start the range at different position by comparing
- // the document position of it with 'enlargeable' node.
+ // Close the range either before the found block start (text]
...
) or at the block end (...text])
+ // by comparing the document position with 'enlargeable' node.
this.setEndAt(
blockBoundary,
( !enlargeable && this.checkEndOfBlock()
@@ -1237,10 +1238,17 @@ CKEDITOR.dom.range = function( document )
/**
* Descrease the range to make sure that boundaries
- * always anchor beside text nodes or innermost element.
+ * always anchor beside text nodes or innermost element.
* @param {Number} mode ( CKEDITOR.SHRINK_ELEMENT | CKEDITOR.SHRINK_TEXT ) The shrinking mode.
+ *
+ * - CKEDITOR.SHRINK_ELEMENT
+ * - Shrink the range boundaries to the edge of the innermost element.
+ * - CKEDITOR.SHRINK_TEXT
+ * - Shrink the range boudaries to anchor by the side of enclosed text node, range remains if there's no text nodes on boundaries at all.
+ *
+ * @param {Boolean} selectContents Whether result range anchors at the inner OR outer boundary of the node.
*/
- shrink : function( mode )
+ shrink : function( mode, selectContents )
{
// Unable to shrink a collapsed range.
if ( !this.collapsed )
@@ -1315,14 +1323,14 @@ CKEDITOR.dom.range = function( document )
if ( moveStart )
{
var textStart = walker[ mode == CKEDITOR.SHRINK_ELEMENT ? 'lastForward' : 'next']();
- textStart && this.setStartBefore( textStart );
+ textStart && this.setStartAt( textStart, selectContents ? CKEDITOR.POSITION_AFTER_START : CKEDITOR.POSITION_BEFORE_START );
}
if ( moveEnd )
{
walker.reset();
var textEnd = walker[ mode == CKEDITOR.SHRINK_ELEMENT ? 'lastBackward' : 'previous']();
- textEnd && this.setEndAfter( textEnd );
+ textEnd && this.setEndAt( textEnd, selectContents ? CKEDITOR.POSITION_BEFORE_END : CKEDITOR.POSITION_AFTER_END );
}
return !!( moveStart || moveEnd );
@@ -1382,6 +1390,11 @@ CKEDITOR.dom.range = function( document )
// we will not need this check for our use of this class so we can
// ignore it for now.
+ // Fixing invalid range start inside dtd empty elements.
+ if( startNode.type == CKEDITOR.NODE_ELEMENT
+ && CKEDITOR.dtd.$empty[ startNode.getName() ] )
+ startNode = startNode.getParent(), startOffset = startNode.getIndex();
+
this.startContainer = startNode;
this.startOffset = startOffset;
@@ -1408,6 +1421,11 @@ CKEDITOR.dom.range = function( document )
// will not need this check for our use of this class so we can ignore
// it for now.
+ // Fixing invalid range end inside dtd empty elements.
+ if( endNode.type == CKEDITOR.NODE_ELEMENT
+ && CKEDITOR.dtd.$empty[ endNode.getName() ] )
+ endNode = endNode.getParent(), endOffset = endNode.getIndex() + 1;
+
this.endContainer = endNode;
this.endOffset = endOffset;
@@ -1628,12 +1646,12 @@ CKEDITOR.dom.range = function( document )
CKEDITOR.POSITION_AFTER_START
: CKEDITOR.POSITION_BEFORE_END );
- var walker = new CKEDITOR.dom.walker( walkerRange ),
- retval = false;
+ var walker = new CKEDITOR.dom.walker( walkerRange );
walker.evaluator = elementBoundaryEval;
return walker[ checkType == CKEDITOR.START ?
'checkBackward' : 'checkForward' ]();
},
+
// Calls to this function may produce changes to the DOM. The range may
// be updated to reflect such changes.
checkStartOfBlock : function()
@@ -1779,8 +1797,15 @@ CKEDITOR.dom.range = function( document )
*/
getEnclosedNode : function()
{
- var walkerRange = this.clone(),
- walker = new CKEDITOR.dom.walker( walkerRange ),
+ var walkerRange = this.clone();
+
+ // Optimize and analyze the range to avoid DOM destructive nature of walker. (#5780)
+ walkerRange.optimize();
+ if ( walkerRange.startContainer.type != CKEDITOR.NODE_ELEMENT
+ || walkerRange.endContainer.type != CKEDITOR.NODE_ELEMENT )
+ return null;
+
+ var walker = new CKEDITOR.dom.walker( walkerRange ),
isNotBookmarks = CKEDITOR.dom.walker.bookmark( true ),
isNotWhitespaces = CKEDITOR.dom.walker.whitespaces( true ),
evaluator = function( node )
@@ -1826,11 +1851,15 @@ CKEDITOR.ENLARGE_LIST_ITEM_CONTENTS = 3;
/**
* Check boundary types.
- * @see CKEDITOR.dom.range::checkBoundaryOfElement
+ * @see CKEDITOR.dom.range.prototype.checkBoundaryOfElement
*/
CKEDITOR.START = 1;
CKEDITOR.END = 2;
CKEDITOR.STARTEND = 3;
+/**
+ * Shrink range types.
+ * @see CKEDITOR.dom.range.prototype.shrink
+ */
CKEDITOR.SHRINK_ELEMENT = 1;
CKEDITOR.SHRINK_TEXT = 2;