JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
vanilla ckeditor-3.6.3
[ckeditor.git] / _source / core / dom / walker.js
index 7f430b8..3d19425 100644 (file)
@@ -1,5 +1,5 @@
 /*\r
-Copyright (c) 2003-2011, CKSource - Frederico Knabben. All rights reserved.\r
+Copyright (c) 2003-2012, CKSource - Frederico Knabben. All rights reserved.\r
 For licensing, see LICENSE.html or http://ckeditor.com/license\r
 */\r
 \r
@@ -8,40 +8,50 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
        // This function is to be called under a "walker" instance scope.\r
        function iterate( rtl, breakOnFalse )\r
        {\r
+               var range = this.range;\r
+\r
                // Return null if we have reached the end.\r
                if ( this._.end )\r
                        return null;\r
 \r
-               var node,\r
-                       range = this.range,\r
-                       guard,\r
-                       userGuard = this.guard,\r
-                       type = this.type,\r
-                       getSourceNodeFn = ( rtl ? 'getPreviousSourceNode' : 'getNextSourceNode' );\r
-\r
                // This is the first call. Initialize it.\r
                if ( !this._.start )\r
                {\r
                        this._.start = 1;\r
 \r
-                       // Trim text nodes and optmize the range boundaries. DOM changes\r
-                       // may happen at this point.\r
-                       range.trim();\r
-\r
                        // A collapsed range must return null at first call.\r
                        if ( range.collapsed )\r
                        {\r
                                this.end();\r
                                return null;\r
                        }\r
+\r
+                       // Move outside of text node edges.\r
+                       range.optimize();\r
                }\r
 \r
+               var node,\r
+                       startCt = range.startContainer,\r
+                       endCt = range.endContainer,\r
+                       startOffset = range.startOffset,\r
+                       endOffset = range.endOffset,\r
+                       guard,\r
+                       userGuard = this.guard,\r
+                       type = this.type,\r
+                       getSourceNodeFn = ( rtl ? 'getPreviousSourceNode' : 'getNextSourceNode' );\r
+\r
                // Create the LTR guard function, if necessary.\r
                if ( !rtl && !this._.guardLTR )\r
                {\r
-                       // Gets the node that stops the walker when going LTR.\r
-                       var limitLTR = range.endContainer,\r
-                               blockerLTR = limitLTR.getChild( range.endOffset );\r
+                       // The node that stops walker from moving up.\r
+                       var limitLTR = endCt.type == CKEDITOR.NODE_ELEMENT ?\r
+                                                  endCt :\r
+                                                  endCt.getParent();\r
+\r
+                       // The node that stops the walker from going to next.\r
+                       var blockerLTR = endCt.type == CKEDITOR.NODE_ELEMENT ?\r
+                                                        endCt.getChild( endOffset ) :\r
+                                                        endCt.getNext();\r
 \r
                        this._.guardLTR = function( node, movingOut )\r
                        {\r
@@ -54,9 +64,16 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
                // Create the RTL guard function, if necessary.\r
                if ( rtl && !this._.guardRTL )\r
                {\r
-                       // Gets the node that stops the walker when going LTR.\r
-                       var limitRTL = range.startContainer,\r
-                               blockerRTL = ( range.startOffset > 0 ) && limitRTL.getChild( range.startOffset - 1 );\r
+                       // The node that stops walker from moving up.\r
+                       var limitRTL = startCt.type == CKEDITOR.NODE_ELEMENT ?\r
+                                                  startCt :\r
+                                                  startCt.getParent();\r
+\r
+                       // The node that stops the walker from going to next.\r
+                       var blockerRTL = startCt.type == CKEDITOR.NODE_ELEMENT ?\r
+                                                startOffset ?\r
+                                                startCt.getChild( startOffset - 1 ) : null :\r
+                                                startCt.getPrevious();\r
 \r
                        this._.guardRTL = function( node, movingOut )\r
                        {\r
@@ -89,35 +106,33 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
                else\r
                {\r
                        // Get the first node to be returned.\r
-\r
                        if ( rtl )\r
                        {\r
-                               node = range.endContainer;\r
+                               node = endCt;\r
 \r
-                               if ( range.endOffset > 0 )\r
+                               if ( node.type == CKEDITOR.NODE_ELEMENT )\r
                                {\r
-                                       node = node.getChild( range.endOffset - 1 );\r
-                                       if ( guard( node ) === false )\r
-                                               node = null;\r
+                                       if ( endOffset > 0 )\r
+                                               node = node.getChild( endOffset - 1 );\r
+                                       else\r
+                                               node = ( guard ( node, true ) === false ) ?\r
+                                                       null : node.getPreviousSourceNode( true, type, guard );\r
                                }\r
-                               else\r
-                                       node = ( guard ( node, true ) === false ) ?\r
-                                               null : node.getPreviousSourceNode( true, type, guard );\r
                        }\r
                        else\r
                        {\r
-                               node = range.startContainer;\r
-                               node = node.getChild( range.startOffset );\r
+                               node = startCt;\r
 \r
-                               if ( node )\r
+                               if ( node.type == CKEDITOR.NODE_ELEMENT )\r
                                {\r
-                                       if ( guard( node ) === false )\r
-                                               node = null;\r
+                                       if ( ! ( node = node.getChild( startOffset ) ) )\r
+                                               node = ( guard ( startCt, true ) === false ) ?\r
+                                                       null : startCt.getNextSourceNode( true, type, guard ) ;\r
                                }\r
-                               else\r
-                                       node = ( guard ( range.startContainer, true ) === false ) ?\r
-                                               null : range.startContainer.getNextSourceNode( true, type, guard ) ;\r
                        }\r
+\r
+                       if ( node && guard( node ) === false )\r
+                               node = null;\r
                }\r
 \r
                while ( node && !this._.end )\r
@@ -431,6 +446,25 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
                };\r
        };\r
 \r
+       CKEDITOR.dom.walker.bogus = function( type, isReject )\r
+       {\r
+               function nonEmpty( node )\r
+               {\r
+                       return !isWhitespaces( node ) && !isBookmark( node );\r
+               }\r
+\r
+               return function( node )\r
+               {\r
+                       var parent = node.getParent(),\r
+                               isBogus = !CKEDITOR.env.ie ? node.is && node.is( 'br' ) :\r
+                                         node.getText && tailNbspRegex.test( node.getText() );\r
+\r
+                       isBogus = isBogus && parent.isBlockBoundary() && !!parent.getLast( nonEmpty );\r
+\r
+                       return !! ( isReject ^ isBogus );\r
+               };\r
+       };\r
+\r
        var tailNbspRegex = /^[\t\r\n ]*(?: |\xa0)$/,\r
                isWhitespaces = CKEDITOR.dom.walker.whitespaces(),\r
                isBookmark = CKEDITOR.dom.walker.bookmark(),\r