X-Git-Url: https://jasonwoof.com/gitweb/?p=ckeditor.git;a=blobdiff_plain;f=_source%2Fcore%2Fdom%2Frange.js;h=127f7aaba39ce553c0961f31b471c82436c47d2f;hp=8d30b4fe2bc7ff4afbba7347c3b0899a16cebb63;hb=e7789c1ad838194d45eeee6ac2eb6e55f5cf35a1;hpb=059b4c2fef02528bf1af189f7996e80652faddfb diff --git a/_source/core/dom/range.js b/_source/core/dom/range.js index 8d30b4f..127f7aa 100644 --- a/_source/core/dom/range.js +++ b/_source/core/dom/range.js @@ -925,7 +925,7 @@ CKEDITOR.dom.range = function( document ) siblingText = sibling.getText(); - if ( !(/[^\s\ufeff]/).test( siblingText ) ) // Spaces + Zero Width No-Break Space (U+FEFF) + if ( (/[^\s\ufeff]/).test( siblingText ) ) // Spaces + Zero Width No-Break Space (U+FEFF) sibling = null; else { @@ -1084,7 +1084,7 @@ CKEDITOR.dom.range = function( document ) siblingText = sibling.getText(); - if ( !(/[^\s\ufeff]/).test( siblingText ) ) + if ( (/[^\s\ufeff]/).test( siblingText ) ) sibling = null; else { @@ -1236,6 +1236,100 @@ CKEDITOR.dom.range = function( document ) }, /** + * Descrease the range to make sure that boundaries + * always anchor beside text nodes or innermost element. + * @param {Number} mode ( CKEDITOR.SHRINK_ELEMENT | CKEDITOR.SHRINK_TEXT ) The shrinking mode. + */ + shrink : function( mode ) + { + // Unable to shrink a collapsed range. + if ( !this.collapsed ) + { + mode = mode || CKEDITOR.SHRINK_TEXT; + + var walkerRange = this.clone(); + + var startContainer = this.startContainer, + endContainer = this.endContainer, + startOffset = this.startOffset, + endOffset = this.endOffset, + collapsed = this.collapsed; + + // Whether the start/end boundary is moveable. + var moveStart = 1, + moveEnd = 1; + + if ( startContainer && startContainer.type == CKEDITOR.NODE_TEXT ) + { + if ( !startOffset ) + walkerRange.setStartBefore( startContainer ); + else if ( startOffset >= startContainer.getLength( ) ) + walkerRange.setStartAfter( startContainer ); + else + { + // Enlarge the range properly to avoid walker making + // DOM changes caused by triming the text nodes later. + walkerRange.setStartBefore( startContainer ); + moveStart = 0; + } + } + + if ( endContainer && endContainer.type == CKEDITOR.NODE_TEXT ) + { + if ( !endOffset ) + walkerRange.setEndBefore( endContainer ); + else if ( endOffset >= endContainer.getLength( ) ) + walkerRange.setEndAfter( endContainer ); + else + { + walkerRange.setEndAfter( endContainer ); + moveEnd = 0; + } + } + + var walker = new CKEDITOR.dom.walker( walkerRange ); + + walker.evaluator = function( node ) + { + return node.type == ( mode == CKEDITOR.SHRINK_ELEMENT ? + CKEDITOR.NODE_ELEMENT : CKEDITOR.NODE_TEXT ); + }; + + var currentElement; + walker.guard = function( node, movingOut ) + { + // Stop when we're shrink in element mode while encountering a text node. + if ( mode == CKEDITOR.SHRINK_ELEMENT && node.type == CKEDITOR.NODE_TEXT ) + return false; + + // Stop when we've already walked "through" an element. + if ( movingOut && node.equals( currentElement ) ) + return false; + + if ( !movingOut && node.type == CKEDITOR.NODE_ELEMENT ) + currentElement = node; + + return true; + }; + + if ( moveStart ) + { + var textStart = walker[ mode == CKEDITOR.SHRINK_ELEMENT ? 'lastForward' : 'next'](); + textStart && this.setStartBefore( textStart ); + } + + if ( moveEnd ) + { + walker.reset(); + var textEnd = walker[ mode == CKEDITOR.SHRINK_ELEMENT ? 'lastBackward' : 'previous'](); + textEnd && this.setEndAfter( textEnd ); + } + + return !!( moveStart || moveEnd ); + } + }, + + /** * Inserts a node at the start of the range. The range will be expanded * the contain the node. */ @@ -1623,6 +1717,10 @@ CKEDITOR.dom.range = function( document ) { var isEditable; + // Empty elements are rejected. + if ( CKEDITOR.dtd.$empty[ el.getName() ] ) + return false; + while ( el && el.type == CKEDITOR.NODE_ELEMENT ) { isEditable = el.isEditable(); @@ -1733,3 +1831,6 @@ CKEDITOR.ENLARGE_LIST_ITEM_CONTENTS = 3; CKEDITOR.START = 1; CKEDITOR.END = 2; CKEDITOR.STARTEND = 3; + +CKEDITOR.SHRINK_ELEMENT = 1; +CKEDITOR.SHRINK_TEXT = 2;