if ( CKEDITOR.tools.trim( node.getText() ).length )\r
return false;\r
}\r
- else\r
+ else if( node.type == CKEDITOR.NODE_ELEMENT )\r
{\r
// If there are non-empty inline elements (e.g. <img />), then we're not\r
// at the start.\r
|| node.getParent().hasAttribute( '_fck_bookmark' );\r
}\r
\r
+ var whitespaceEval = new CKEDITOR.dom.walker.whitespaces(),\r
+ bookmarkEval = new CKEDITOR.dom.walker.bookmark();\r
+\r
+ function nonWhitespaceOrBookmarkEval( node )\r
+ {\r
+ // Whitespaces and bookmark nodes are to be ignored.\r
+ return !whitespaceEval( node ) && !bookmarkEval( node );\r
+ }\r
+\r
CKEDITOR.dom.range.prototype =\r
{\r
clone : function()\r
this.setStartAt(\r
blockBoundary,\r
!blockBoundary.is( 'br' ) &&\r
- ( !enlargeable || blockBoundary.contains( enlargeable ) ) ?\r
+ ( !enlargeable && this.checkStartOfBlock()\r
+ || enlargeable && blockBoundary.contains( enlargeable ) ) ?\r
CKEDITOR.POSITION_AFTER_START :\r
CKEDITOR.POSITION_AFTER_END );\r
\r
// the document position of it with 'enlargeable' node.\r
this.setEndAt(\r
blockBoundary,\r
- !blockBoundary.is( 'br' ) &&\r
- ( !enlargeable || blockBoundary.contains( enlargeable ) ) ?\r
+ ( !enlargeable && this.checkEndOfBlock()\r
+ || enlargeable && blockBoundary.contains( enlargeable ) ) ?\r
CKEDITOR.POSITION_BEFORE_END :\r
CKEDITOR.POSITION_BEFORE_START );\r
// We must include the <br> at the end of range if there's\r
}\r
else\r
{\r
- // Extract the contents of the block from the selection point to the end\r
- // of its contents.\r
- this.setEndAt( startBlock, CKEDITOR.POSITION_BEFORE_END );\r
- var documentFragment = this.extractContents();\r
-\r
- // Duplicate the block element after it.\r
- endBlock = startBlock.clone( false );\r
-\r
- // Place the extracted contents into the duplicated block.\r
- documentFragment.appendTo( endBlock );\r
- endBlock.insertAfter( startBlock );\r
- this.moveToPosition( startBlock, CKEDITOR.POSITION_AFTER_END );\r
-\r
+ endBlock = this.splitElement( startBlock );\r
// In Gecko, the last child node must be a bogus <br>.\r
// Note: bogus <br> added under <ul> or <ol> would cause\r
// lists to be incorrectly rendered.\r
},\r
\r
/**\r
+ * Branch the specified element from the collapsed range position and\r
+ * place the caret between the two result branches.\r
+ * Note: The range must be collapsed and been enclosed by this element.\r
+ * @param {CKEDITOR.dom.element} element\r
+ * @return {CKEDITOR.dom.element} Root element of the new branch after the split.\r
+ */\r
+ splitElement : function( toSplit )\r
+ {\r
+ if ( !this.collapsed )\r
+ return null;\r
+\r
+ // Extract the contents of the block from the selection point to the end\r
+ // of its contents.\r
+ this.setEndAt( toSplit, CKEDITOR.POSITION_BEFORE_END );\r
+ var documentFragment = this.extractContents();\r
+\r
+ // Duplicate the element after it.\r
+ var clone = toSplit.clone( false );\r
+\r
+ // Place the extracted contents into the duplicated element.\r
+ documentFragment.appendTo( clone );\r
+ clone.insertAfter( toSplit );\r
+ this.moveToPosition( toSplit, CKEDITOR.POSITION_AFTER_END );\r
+ return clone;\r
+ },\r
+\r
+ /**\r
* Check whether current range is on the inner edge of the specified element.\r
* @param {Number} checkType ( CKEDITOR.START | CKEDITOR.END ) The checking side.\r
* @param {CKEDITOR.dom.element} element The target element to check.\r
* element. For example, in an element tree like\r
* "<p><b><i></i></b> Text</p>", the start editing point is\r
* "<p><b><i>^</i></b> Text</p>" (inside <i>).\r
- * @param {CKEDITOR.dom.element} targetElement The element into which\r
- * look for the editing spot.\r
+ * @param {CKEDITOR.dom.element} el The element into which look for the\r
+ * editing spot.\r
*/\r
- moveToElementEditStart : function( targetElement )\r
+ moveToElementEditStart : function( el )\r
{\r
- var editableElement;\r
+ var isEditable;\r
\r
- while ( targetElement && targetElement.type == CKEDITOR.NODE_ELEMENT )\r
+ while ( el && el.type == CKEDITOR.NODE_ELEMENT )\r
{\r
- if ( targetElement.isEditable() )\r
- editableElement = targetElement;\r
- else if ( editableElement )\r
- break ; // If we already found an editable element, stop the loop.\r
+ isEditable = el.isEditable();\r
\r
- targetElement = targetElement.getFirst();\r
- }\r
+ // If an editable element is found, move inside it.\r
+ if ( isEditable )\r
+ this.moveToPosition( el, CKEDITOR.POSITION_AFTER_START );\r
+ // Stop immediately if we've found a non editable inline element (e.g <img>).\r
+ else if ( CKEDITOR.dtd.$inline[ el.getName() ] )\r
+ {\r
+ this.moveToPosition( el, CKEDITOR.POSITION_BEFORE_START );\r
+ return true;\r
+ }\r
\r
- if ( editableElement )\r
- {\r
- this.moveToPosition(editableElement, CKEDITOR.POSITION_AFTER_START);\r
- return true;\r
+ // Non-editable non-inline elements are to be bypassed, getting the next one.\r
+ if ( CKEDITOR.dtd.$empty[ el.getName() ] )\r
+ el = el.getNext( nonWhitespaceOrBookmarkEval );\r
+ else\r
+ el = el.getFirst( nonWhitespaceOrBookmarkEval );\r
+\r
+ // Stop immediately if we've found a text node.\r
+ if ( el && el.type == CKEDITOR.NODE_TEXT )\r
+ {\r
+ this.moveToPosition( el, CKEDITOR.POSITION_BEFORE_START );\r
+ return true;\r
+ }\r
}\r
- else\r
- return false;\r
+\r
+ return isEditable;\r
},\r
\r
/**\r