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;