\r
siblingText = sibling.getText();\r
\r
- if ( !(/[^\s\ufeff]/).test( siblingText ) ) // Spaces + Zero Width No-Break Space (U+FEFF)\r
+ if ( (/[^\s\ufeff]/).test( siblingText ) ) // Spaces + Zero Width No-Break Space (U+FEFF)\r
sibling = null;\r
else\r
{\r
\r
siblingText = sibling.getText();\r
\r
- if ( !(/[^\s\ufeff]/).test( siblingText ) )\r
+ if ( (/[^\s\ufeff]/).test( siblingText ) )\r
sibling = null;\r
else\r
{\r
},\r
\r
/**\r
+ * Descrease the range to make sure that boundaries\r
+ * always anchor beside text nodes or innermost element.\r
+ * @param {Number} mode ( CKEDITOR.SHRINK_ELEMENT | CKEDITOR.SHRINK_TEXT ) The shrinking mode.\r
+ */\r
+ shrink : function( mode )\r
+ {\r
+ // Unable to shrink a collapsed range.\r
+ if ( !this.collapsed )\r
+ {\r
+ mode = mode || CKEDITOR.SHRINK_TEXT;\r
+\r
+ var walkerRange = this.clone();\r
+\r
+ var startContainer = this.startContainer,\r
+ endContainer = this.endContainer,\r
+ startOffset = this.startOffset,\r
+ endOffset = this.endOffset,\r
+ collapsed = this.collapsed;\r
+\r
+ // Whether the start/end boundary is moveable.\r
+ var moveStart = 1,\r
+ moveEnd = 1;\r
+\r
+ if ( startContainer && startContainer.type == CKEDITOR.NODE_TEXT )\r
+ {\r
+ if ( !startOffset )\r
+ walkerRange.setStartBefore( startContainer );\r
+ else if ( startOffset >= startContainer.getLength( ) )\r
+ walkerRange.setStartAfter( startContainer );\r
+ else\r
+ {\r
+ // Enlarge the range properly to avoid walker making\r
+ // DOM changes caused by triming the text nodes later.\r
+ walkerRange.setStartBefore( startContainer );\r
+ moveStart = 0;\r
+ }\r
+ }\r
+\r
+ if ( endContainer && endContainer.type == CKEDITOR.NODE_TEXT )\r
+ {\r
+ if ( !endOffset )\r
+ walkerRange.setEndBefore( endContainer );\r
+ else if ( endOffset >= endContainer.getLength( ) )\r
+ walkerRange.setEndAfter( endContainer );\r
+ else\r
+ {\r
+ walkerRange.setEndAfter( endContainer );\r
+ moveEnd = 0;\r
+ }\r
+ }\r
+\r
+ var walker = new CKEDITOR.dom.walker( walkerRange );\r
+\r
+ walker.evaluator = function( node )\r
+ {\r
+ return node.type == ( mode == CKEDITOR.SHRINK_ELEMENT ?\r
+ CKEDITOR.NODE_ELEMENT : CKEDITOR.NODE_TEXT );\r
+ };\r
+\r
+ var currentElement;\r
+ walker.guard = function( node, movingOut )\r
+ {\r
+ // Stop when we're shrink in element mode while encountering a text node.\r
+ if ( mode == CKEDITOR.SHRINK_ELEMENT && node.type == CKEDITOR.NODE_TEXT )\r
+ return false;\r
+\r
+ // Stop when we've already walked "through" an element.\r
+ if ( movingOut && node.equals( currentElement ) )\r
+ return false;\r
+\r
+ if ( !movingOut && node.type == CKEDITOR.NODE_ELEMENT )\r
+ currentElement = node;\r
+\r
+ return true;\r
+ };\r
+\r
+ if ( moveStart )\r
+ {\r
+ var textStart = walker[ mode == CKEDITOR.SHRINK_ELEMENT ? 'lastForward' : 'next']();\r
+ textStart && this.setStartBefore( textStart );\r
+ }\r
+\r
+ if ( moveEnd )\r
+ {\r
+ walker.reset();\r
+ var textEnd = walker[ mode == CKEDITOR.SHRINK_ELEMENT ? 'lastBackward' : 'previous']();\r
+ textEnd && this.setEndAfter( textEnd );\r
+ }\r
+\r
+ return !!( moveStart || moveEnd );\r
+ }\r
+ },\r
+\r
+ /**\r
* Inserts a node at the start of the range. The range will be expanded\r
* the contain the node.\r
*/\r
{\r
var isEditable;\r
\r
+ // Empty elements are rejected.\r
+ if ( CKEDITOR.dtd.$empty[ el.getName() ] )\r
+ return false;\r
+\r
while ( el && el.type == CKEDITOR.NODE_ELEMENT )\r
{\r
isEditable = el.isEditable();\r
CKEDITOR.START = 1;\r
CKEDITOR.END = 2;\r
CKEDITOR.STARTEND = 3;\r
+\r
+CKEDITOR.SHRINK_ELEMENT = 1;\r
+CKEDITOR.SHRINK_TEXT = 2;\r