JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
vanilla ckeditor-4.0_full
[ckeditor.git] / _source / core / dom / walker.js
diff --git a/_source/core/dom/walker.js b/_source/core/dom/walker.js
deleted file mode 100644 (file)
index 569ac57..0000000
+++ /dev/null
@@ -1,520 +0,0 @@
-/*\r
-Copyright (c) 2003-2013, CKSource - Frederico Knabben. All rights reserved.\r
-For licensing, see LICENSE.html or http://ckeditor.com/license\r
-*/\r
-\r
-(function()\r
-{\r
-       // 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
-               // This is the first call. Initialize it.\r
-               if ( !this._.start )\r
-               {\r
-                       this._.start = 1;\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
-                       // 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
-                               return ( ( !movingOut || !limitLTR.equals( node ) )\r
-                                       && ( !blockerLTR || !node.equals( blockerLTR ) )\r
-                                       && ( node.type != CKEDITOR.NODE_ELEMENT || !movingOut || node.getName() != 'body' ) );\r
-                       };\r
-               }\r
-\r
-               // Create the RTL guard function, if necessary.\r
-               if ( rtl && !this._.guardRTL )\r
-               {\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
-                               return ( ( !movingOut || !limitRTL.equals( node ) )\r
-                                       && ( !blockerRTL || !node.equals( blockerRTL ) )\r
-                                       && ( node.type != CKEDITOR.NODE_ELEMENT || !movingOut || node.getName() != 'body' ) );\r
-                       };\r
-               }\r
-\r
-               // Define which guard function to use.\r
-               var stopGuard = rtl ? this._.guardRTL : this._.guardLTR;\r
-\r
-               // Make the user defined guard function participate in the process,\r
-               // otherwise simply use the boundary guard.\r
-               if ( userGuard )\r
-               {\r
-                       guard = function( node, movingOut )\r
-                       {\r
-                               if ( stopGuard( node, movingOut ) === false )\r
-                                       return false;\r
-\r
-                               return userGuard( node, movingOut );\r
-                       };\r
-               }\r
-               else\r
-                       guard = stopGuard;\r
-\r
-               if ( this.current )\r
-                       node = this.current[ getSourceNodeFn ]( false, type, guard );\r
-               else\r
-               {\r
-                       // Get the first node to be returned.\r
-                       if ( rtl )\r
-                       {\r
-                               node = endCt;\r
-\r
-                               if ( node.type == CKEDITOR.NODE_ELEMENT )\r
-                               {\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
-                       }\r
-                       else\r
-                       {\r
-                               node = startCt;\r
-\r
-                               if ( node.type == CKEDITOR.NODE_ELEMENT )\r
-                               {\r
-                                       if ( ! ( node = node.getChild( startOffset ) ) )\r
-                                               node = ( guard ( startCt, true ) === false ) ?\r
-                                                       null : startCt.getNextSourceNode( true, type, guard ) ;\r
-                               }\r
-                       }\r
-\r
-                       if ( node && guard( node ) === false )\r
-                               node = null;\r
-               }\r
-\r
-               while ( node && !this._.end )\r
-               {\r
-                       this.current = node;\r
-\r
-                       if ( !this.evaluator || this.evaluator( node ) !== false )\r
-                       {\r
-                               if ( !breakOnFalse )\r
-                                       return node;\r
-                       }\r
-                       else if ( breakOnFalse && this.evaluator )\r
-                               return false;\r
-\r
-                       node = node[ getSourceNodeFn ]( false, type, guard );\r
-               }\r
-\r
-               this.end();\r
-               return this.current = null;\r
-       }\r
-\r
-       function iterateToLast( rtl )\r
-       {\r
-               var node, last = null;\r
-\r
-               while ( ( node = iterate.call( this, rtl ) ) )\r
-                       last = node;\r
-\r
-               return last;\r
-       }\r
-\r
-       CKEDITOR.dom.walker = CKEDITOR.tools.createClass(\r
-       {\r
-               /**\r
-                * Utility class to "walk" the DOM inside a range boundaries. If\r
-                * necessary, partially included nodes (text nodes) are broken to\r
-                * reflect the boundaries limits, so DOM and range changes may happen.\r
-                * Outside changes to the range may break the walker.\r
-                *\r
-                * The walker may return nodes that are not totaly included into the\r
-                * range boundaires. Let's take the following range representation,\r
-                * where the square brackets indicate the boundaries:\r
-                *\r
-                * [<p>Some <b>sample] text</b>\r
-                *\r
-                * While walking forward into the above range, the following nodes are\r
-                * returned: <p>, "Some ", <b> and "sample". Going\r
-                * backwards instead we have: "sample" and "Some ". So note that the\r
-                * walker always returns nodes when "entering" them, but not when\r
-                * "leaving" them. The guard function is instead called both when\r
-                * entering and leaving nodes.\r
-                *\r
-                * @constructor\r
-                * @param {CKEDITOR.dom.range} range The range within which walk.\r
-                */\r
-               $ : function( range )\r
-               {\r
-                       this.range = range;\r
-\r
-                       /**\r
-                        * A function executed for every matched node, to check whether\r
-                        * it's to be considered into the walk or not. If not provided, all\r
-                        * matched nodes are considered good.\r
-                        * If the function returns "false" the node is ignored.\r
-                        * @name CKEDITOR.dom.walker.prototype.evaluator\r
-                        * @property\r
-                        * @type Function\r
-                        */\r
-                       // this.evaluator = null;\r
-\r
-                       /**\r
-                        * A function executed for every node the walk pass by to check\r
-                        * whether the walk is to be finished. It's called when both\r
-                        * entering and exiting nodes, as well as for the matched nodes.\r
-                        * If this function returns "false", the walking ends and no more\r
-                        * nodes are evaluated.\r
-                        * @name CKEDITOR.dom.walker.prototype.guard\r
-                        * @property\r
-                        * @type Function\r
-                        */\r
-                       // this.guard = null;\r
-\r
-                       /** @private */\r
-                       this._ = {};\r
-               },\r
-\r
-//             statics :\r
-//             {\r
-//                     /* Creates a CKEDITOR.dom.walker instance to walk inside DOM boundaries set by nodes.\r
-//                      * @param {CKEDITOR.dom.node} startNode The node from wich the walk\r
-//                      *              will start.\r
-//                      * @param {CKEDITOR.dom.node} [endNode] The last node to be considered\r
-//                      *              in the walk. No more nodes are retrieved after touching or\r
-//                      *              passing it. If not provided, the walker stops at the\r
-//                      *              <body> closing boundary.\r
-//                      * @returns {CKEDITOR.dom.walker} A DOM walker for the nodes between the\r
-//                      *              provided nodes.\r
-//                      */\r
-//                     createOnNodes : function( startNode, endNode, startInclusive, endInclusive )\r
-//                     {\r
-//                             var range = new CKEDITOR.dom.range();\r
-//                             if ( startNode )\r
-//                                     range.setStartAt( startNode, startInclusive ? CKEDITOR.POSITION_BEFORE_START : CKEDITOR.POSITION_AFTER_END ) ;\r
-//                             else\r
-//                                     range.setStartAt( startNode.getDocument().getBody(), CKEDITOR.POSITION_AFTER_START ) ;\r
-//\r
-//                             if ( endNode )\r
-//                                     range.setEndAt( endNode, endInclusive ? CKEDITOR.POSITION_AFTER_END : CKEDITOR.POSITION_BEFORE_START ) ;\r
-//                             else\r
-//                                     range.setEndAt( startNode.getDocument().getBody(), CKEDITOR.POSITION_BEFORE_END ) ;\r
-//\r
-//                             return new CKEDITOR.dom.walker( range );\r
-//                     }\r
-//             },\r
-//\r
-               proto :\r
-               {\r
-                       /**\r
-                        * Stop walking. No more nodes are retrieved if this function gets\r
-                        * called.\r
-                        */\r
-                       end : function()\r
-                       {\r
-                               this._.end = 1;\r
-                       },\r
-\r
-                       /**\r
-                        * Retrieves the next node (at right).\r
-                        * @returns {CKEDITOR.dom.node} The next node or null if no more\r
-                        *              nodes are available.\r
-                        */\r
-                       next : function()\r
-                       {\r
-                               return iterate.call( this );\r
-                       },\r
-\r
-                       /**\r
-                        * Retrieves the previous node (at left).\r
-                        * @returns {CKEDITOR.dom.node} The previous node or null if no more\r
-                        *              nodes are available.\r
-                        */\r
-                       previous : function()\r
-                       {\r
-                               return iterate.call( this, 1 );\r
-                       },\r
-\r
-                       /**\r
-                        * Check all nodes at right, executing the evaluation fuction.\r
-                        * @returns {Boolean} "false" if the evaluator function returned\r
-                        *              "false" for any of the matched nodes. Otherwise "true".\r
-                        */\r
-                       checkForward : function()\r
-                       {\r
-                               return iterate.call( this, 0, 1 ) !== false;\r
-                       },\r
-\r
-                       /**\r
-                        * Check all nodes at left, executing the evaluation fuction.\r
-                        * @returns {Boolean} "false" if the evaluator function returned\r
-                        *              "false" for any of the matched nodes. Otherwise "true".\r
-                        */\r
-                       checkBackward : function()\r
-                       {\r
-                               return iterate.call( this, 1, 1 ) !== false;\r
-                       },\r
-\r
-                       /**\r
-                        * Executes a full walk forward (to the right), until no more nodes\r
-                        * are available, returning the last valid node.\r
-                        * @returns {CKEDITOR.dom.node} The last node at the right or null\r
-                        *              if no valid nodes are available.\r
-                        */\r
-                       lastForward : function()\r
-                       {\r
-                               return iterateToLast.call( this );\r
-                       },\r
-\r
-                       /**\r
-                        * Executes a full walk backwards (to the left), until no more nodes\r
-                        * are available, returning the last valid node.\r
-                        * @returns {CKEDITOR.dom.node} The last node at the left or null\r
-                        *              if no valid nodes are available.\r
-                        */\r
-                       lastBackward : function()\r
-                       {\r
-                               return iterateToLast.call( this, 1 );\r
-                       },\r
-\r
-                       reset : function()\r
-                       {\r
-                               delete this.current;\r
-                               this._ = {};\r
-                       }\r
-\r
-               }\r
-       });\r
-\r
-       /*\r
-        * Anything whose display computed style is block, list-item, table,\r
-        * table-row-group, table-header-group, table-footer-group, table-row,\r
-        * table-column-group, table-column, table-cell, table-caption, or whose node\r
-        * name is hr, br (when enterMode is br only) is a block boundary.\r
-        */\r
-       var blockBoundaryDisplayMatch =\r
-       {\r
-               block : 1,\r
-               'list-item' : 1,\r
-               table : 1,\r
-               'table-row-group' : 1,\r
-               'table-header-group' : 1,\r
-               'table-footer-group' : 1,\r
-               'table-row' : 1,\r
-               'table-column-group' : 1,\r
-               'table-column' : 1,\r
-               'table-cell' : 1,\r
-               'table-caption' : 1\r
-       };\r
-\r
-       CKEDITOR.dom.element.prototype.isBlockBoundary = function( customNodeNames )\r
-       {\r
-               var nodeNameMatches = customNodeNames ?\r
-                       CKEDITOR.tools.extend( {}, CKEDITOR.dtd.$block, customNodeNames || {} ) :\r
-                       CKEDITOR.dtd.$block;\r
-\r
-               // Don't consider floated formatting as block boundary, fall back to dtd check in that case. (#6297)\r
-               return this.getComputedStyle( 'float' ) == 'none' && blockBoundaryDisplayMatch[ this.getComputedStyle( 'display' ) ]\r
-                               || nodeNameMatches[ this.getName() ];\r
-       };\r
-\r
-       CKEDITOR.dom.walker.blockBoundary = function( customNodeNames )\r
-       {\r
-               return function( node , type )\r
-               {\r
-                       return ! ( node.type == CKEDITOR.NODE_ELEMENT\r
-                                               && node.isBlockBoundary( customNodeNames ) );\r
-               };\r
-       };\r
-\r
-       CKEDITOR.dom.walker.listItemBoundary = function()\r
-       {\r
-                       return this.blockBoundary( { br : 1 } );\r
-       };\r
-\r
-       /**\r
-        * Whether the to-be-evaluated node is a bookmark node OR bookmark node\r
-        * inner contents.\r
-        * @param {Boolean} contentOnly Whether only test againt the text content of\r
-        * bookmark node instead of the element itself(default).\r
-        * @param {Boolean} isReject Whether should return 'false' for the bookmark\r
-        * node instead of 'true'(default).\r
-        */\r
-       CKEDITOR.dom.walker.bookmark = function( contentOnly, isReject )\r
-       {\r
-               function isBookmarkNode( node )\r
-               {\r
-                       return ( node && node.getName\r
-                                       && node.getName() == 'span'\r
-                                       && node.data( 'cke-bookmark' ) );\r
-               }\r
-\r
-               return function( node )\r
-               {\r
-                       var isBookmark, parent;\r
-                       // Is bookmark inner text node?\r
-                       isBookmark = ( node && !node.getName && ( parent = node.getParent() )\r
-                                               && isBookmarkNode( parent ) );\r
-                       // Is bookmark node?\r
-                       isBookmark = contentOnly ? isBookmark : isBookmark || isBookmarkNode( node );\r
-                       return !! ( isReject ^ isBookmark );\r
-               };\r
-       };\r
-\r
-       /**\r
-        * Whether the node is a text node containing only whitespaces characters.\r
-        * @param isReject\r
-        */\r
-       CKEDITOR.dom.walker.whitespaces = function( isReject )\r
-       {\r
-               return function( node )\r
-               {\r
-                       var isWhitespace;\r
-                       if ( node && node.type == CKEDITOR.NODE_TEXT )\r
-                       {\r
-                               // whitespace, as well as the text cursor filler node we used in Webkit. (#9384)\r
-                               isWhitespace = !CKEDITOR.tools.trim( node.getText() ) ||\r
-                                       CKEDITOR.env.webkit && node.getText() == '\u200b';\r
-                       }\r
-\r
-                       return !! ( isReject ^ isWhitespace );\r
-               };\r
-       };\r
-\r
-       /**\r
-        * Whether the node is invisible in wysiwyg mode.\r
-        * @param isReject\r
-        */\r
-       CKEDITOR.dom.walker.invisible = function( isReject )\r
-       {\r
-               var whitespace = CKEDITOR.dom.walker.whitespaces();\r
-               return function( node )\r
-               {\r
-                       var invisible;\r
-\r
-                       if ( whitespace( node ) )\r
-                               invisible = 1;\r
-                       else\r
-                       {\r
-                               // Visibility should be checked on element.\r
-                               if ( node.type == CKEDITOR.NODE_TEXT )\r
-                                       node = node.getParent();\r
-\r
-                               // Nodes that take no spaces in wysiwyg:\r
-                               // 1. White-spaces but not including NBSP;\r
-                               // 2. Empty inline elements, e.g. <b></b> we're checking here\r
-                               // 'offsetHeight' instead of 'offsetWidth' for properly excluding\r
-                               // all sorts of empty paragraph, e.g. <br />.\r
-                               invisible = !node.$.offsetHeight;\r
-                       }\r
-\r
-                       return !! ( isReject ^ invisible );\r
-               };\r
-       };\r
-\r
-       CKEDITOR.dom.walker.nodeType = function( type, isReject )\r
-       {\r
-               return function( node )\r
-               {\r
-                       return !! ( isReject ^ ( node.type == type ) );\r
-               };\r
-       };\r
-\r
-       CKEDITOR.dom.walker.bogus = function( isReject )\r
-       {\r
-               function nonEmpty( node )\r
-               {\r
-                       return !isWhitespaces( node ) && !isBookmark( node );\r
-               }\r
-\r
-               return function( node )\r
-               {\r
-                       var isBogus = !CKEDITOR.env.ie ? node.is && node.is( 'br' ) :\r
-                                         node.getText && tailNbspRegex.test( node.getText() );\r
-\r
-                       if ( isBogus )\r
-                       {\r
-                               var parent = node.getParent(), next = node.getNext( nonEmpty );\r
-                               isBogus = parent.isBlockBoundary() &&\r
-                                         ( !next ||\r
-                                           next.type == CKEDITOR.NODE_ELEMENT &&\r
-                                           next.isBlockBoundary() );\r
-                       }\r
-\r
-                       return !! ( isReject ^ isBogus );\r
-               };\r
-       };\r
-\r
-       var tailNbspRegex = /^[\t\r\n ]*(?:&nbsp;|\xa0)$/,\r
-               isWhitespaces = CKEDITOR.dom.walker.whitespaces(),\r
-               isBookmark = CKEDITOR.dom.walker.bookmark(),\r
-               toSkip = function( node )\r
-               {\r
-                       return isBookmark( node )\r
-                                       || isWhitespaces( node )\r
-                                       || node.type == CKEDITOR.NODE_ELEMENT\r
-                                       && node.getName() in CKEDITOR.dtd.$inline\r
-                                       && !( node.getName() in CKEDITOR.dtd.$empty );\r
-               };\r
-\r
-       // Check if there's a filler node at the end of an element, and return it.\r
-       CKEDITOR.dom.element.prototype.getBogus = function()\r
-       {\r
-               // Bogus are not always at the end, e.g. <p><a>text<br /></a></p> (#7070).\r
-               var tail = this;\r
-               do { tail = tail.getPreviousSourceNode(); }\r
-               while ( toSkip( tail ) )\r
-\r
-               if ( tail && ( !CKEDITOR.env.ie ? tail.is && tail.is( 'br' )\r
-                               : tail.getText && tailNbspRegex.test( tail.getText() ) ) )\r
-               {\r
-                       return tail;\r
-               }\r
-               return false;\r
-       };\r
-\r
-})();\r