JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
vanilla ckeditor-3.0.2
[ckeditor.git] / _source / core / dom / range.js
index 5b1681f..a8b102d 100644 (file)
@@ -278,7 +278,7 @@ CKEDITOR.dom.range = function( document )
                                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
@@ -308,6 +308,15 @@ CKEDITOR.dom.range = function( document )
                            || 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
@@ -1183,7 +1192,8 @@ CKEDITOR.dom.range = function( document )
                                        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
@@ -1208,8 +1218,8 @@ CKEDITOR.dom.range = function( document )
                                        // 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
@@ -1457,19 +1467,7 @@ CKEDITOR.dom.range = function( document )
                                }\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
@@ -1488,6 +1486,33 @@ CKEDITOR.dom.range = function( document )
                },\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
@@ -1583,30 +1608,42 @@ CKEDITOR.dom.range = function( document )
                 * element. For example, in an element tree like\r
                 * "&lt;p&gt;&lt;b&gt;&lt;i&gt;&lt;/i&gt;&lt;/b&gt; Text&lt;/p&gt;", the start editing point is\r
                 * "&lt;p&gt;&lt;b&gt;&lt;i&gt;^&lt;/i&gt;&lt;/b&gt; Text&lt;/p&gt;" (inside &lt;i&gt;).\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