X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;ds=sidebyside;f=_source%2Fcore%2Fdom%2Fwalker.js;h=569ac5719040e21fda2b857758baf4df138305f9;hb=a272c66d841421f8bf933c16535bdcde1c4649fc;hp=944e12b67bfeb2a1f6fdb2d52c75797b42ef98f6;hpb=9afde8772159bd3436f1f5b7862960307710ae5a;p=ckeditor.git
diff --git a/_source/core/dom/walker.js b/_source/core/dom/walker.js
index 944e12b..569ac57 100644
--- a/_source/core/dom/walker.js
+++ b/_source/core/dom/walker.js
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
+Copyright (c) 2003-2013, CKSource - Frederico Knabben. All rights reserved.
For licensing, see LICENSE.html or http://ckeditor.com/license
*/
@@ -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.
function iterate( rtl, breakOnFalse )
{
+ var range = this.range;
+
// Return null if we have reached the end.
if ( this._.end )
return null;
- var node,
- range = this.range,
- guard,
- userGuard = this.guard,
- type = this.type,
- getSourceNodeFn = ( rtl ? 'getPreviousSourceNode' : 'getNextSourceNode' );
-
// This is the first call. Initialize it.
if ( !this._.start )
{
this._.start = 1;
- // Trim text nodes and optmize the range boundaries. DOM changes
- // may happen at this point.
- range.trim();
-
// A collapsed range must return null at first call.
if ( range.collapsed )
{
this.end();
return null;
}
+
+ // Move outside of text node edges.
+ range.optimize();
}
+ var node,
+ startCt = range.startContainer,
+ endCt = range.endContainer,
+ startOffset = range.startOffset,
+ endOffset = range.endOffset,
+ guard,
+ userGuard = this.guard,
+ type = this.type,
+ getSourceNodeFn = ( rtl ? 'getPreviousSourceNode' : 'getNextSourceNode' );
+
// Create the LTR guard function, if necessary.
if ( !rtl && !this._.guardLTR )
{
- // Gets the node that stops the walker when going LTR.
- var limitLTR = range.endContainer,
- blockerLTR = limitLTR.getChild( range.endOffset );
+ // The node that stops walker from moving up.
+ var limitLTR = endCt.type == CKEDITOR.NODE_ELEMENT ?
+ endCt :
+ endCt.getParent();
+
+ // The node that stops the walker from going to next.
+ var blockerLTR = endCt.type == CKEDITOR.NODE_ELEMENT ?
+ endCt.getChild( endOffset ) :
+ endCt.getNext();
this._.guardLTR = function( node, movingOut )
{
@@ -54,9 +64,16 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
// Create the RTL guard function, if necessary.
if ( rtl && !this._.guardRTL )
{
- // Gets the node that stops the walker when going LTR.
- var limitRTL = range.startContainer,
- blockerRTL = ( range.startOffset > 0 ) && limitRTL.getChild( range.startOffset - 1 );
+ // The node that stops walker from moving up.
+ var limitRTL = startCt.type == CKEDITOR.NODE_ELEMENT ?
+ startCt :
+ startCt.getParent();
+
+ // The node that stops the walker from going to next.
+ var blockerRTL = startCt.type == CKEDITOR.NODE_ELEMENT ?
+ startOffset ?
+ startCt.getChild( startOffset - 1 ) : null :
+ startCt.getPrevious();
this._.guardRTL = function( node, movingOut )
{
@@ -89,35 +106,33 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
else
{
// Get the first node to be returned.
-
if ( rtl )
{
- node = range.endContainer;
+ node = endCt;
- if ( range.endOffset > 0 )
+ if ( node.type == CKEDITOR.NODE_ELEMENT )
{
- node = node.getChild( range.endOffset - 1 );
- if ( guard( node ) === false )
- node = null;
+ if ( endOffset > 0 )
+ node = node.getChild( endOffset - 1 );
+ else
+ node = ( guard ( node, true ) === false ) ?
+ null : node.getPreviousSourceNode( true, type, guard );
}
- else
- node = ( guard ( node, true ) === false ) ?
- null : node.getPreviousSourceNode( true, type, guard );
}
else
{
- node = range.startContainer;
- node = node.getChild( range.startOffset );
+ node = startCt;
- if ( node )
+ if ( node.type == CKEDITOR.NODE_ELEMENT )
{
- if ( guard( node ) === false )
- node = null;
+ if ( ! ( node = node.getChild( startOffset ) ) )
+ node = ( guard ( startCt, true ) === false ) ?
+ null : startCt.getNextSourceNode( true, type, guard ) ;
}
- else
- node = ( guard ( range.startContainer, true ) === false ) ?
- null : range.startContainer.getNextSourceNode( true, type, guard ) ;
}
+
+ if ( node && guard( node ) === false )
+ node = null;
}
while ( node && !this._.end )
@@ -338,7 +353,9 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
CKEDITOR.dom.element.prototype.isBlockBoundary = function( customNodeNames )
{
- var nodeNameMatches = CKEDITOR.tools.extend( {}, CKEDITOR.dtd.$block, customNodeNames || {} );
+ var nodeNameMatches = customNodeNames ?
+ CKEDITOR.tools.extend( {}, CKEDITOR.dtd.$block, customNodeNames || {} ) :
+ CKEDITOR.dtd.$block;
// Don't consider floated formatting as block boundary, fall back to dtd check in that case. (#6297)
return this.getComputedStyle( 'float' ) == 'none' && blockBoundaryDisplayMatch[ this.getComputedStyle( 'display' ) ]
@@ -396,8 +413,14 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
{
return function( node )
{
- var isWhitespace = node && ( node.type == CKEDITOR.NODE_TEXT )
- && !CKEDITOR.tools.trim( node.getText() );
+ var isWhitespace;
+ if ( node && node.type == CKEDITOR.NODE_TEXT )
+ {
+ // whitespace, as well as the text cursor filler node we used in Webkit. (#9384)
+ isWhitespace = !CKEDITOR.tools.trim( node.getText() ) ||
+ CKEDITOR.env.webkit && node.getText() == '\u200b';
+ }
+
return !! ( isReject ^ isWhitespace );
};
};
@@ -411,28 +434,81 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
var whitespace = CKEDITOR.dom.walker.whitespaces();
return function( node )
{
- // Nodes that take no spaces in wysiwyg:
- // 1. White-spaces but not including NBSP;
- // 2. Empty inline elements, e.g. we're checking here
- // 'offsetHeight' instead of 'offsetWidth' for properly excluding
- // all sorts of empty paragraph, e.g.
.
- var isInvisible = whitespace( node ) || node.is && !node.$.offsetHeight;
- return !! ( isReject ^ isInvisible );
+ var invisible;
+
+ if ( whitespace( node ) )
+ invisible = 1;
+ else
+ {
+ // Visibility should be checked on element.
+ if ( node.type == CKEDITOR.NODE_TEXT )
+ node = node.getParent();
+
+ // Nodes that take no spaces in wysiwyg:
+ // 1. White-spaces but not including NBSP;
+ // 2. Empty inline elements, e.g. we're checking here
+ // 'offsetHeight' instead of 'offsetWidth' for properly excluding
+ // all sorts of empty paragraph, e.g.
.
+ invisible = !node.$.offsetHeight;
+ }
+
+ return !! ( isReject ^ invisible );
+ };
+ };
+
+ CKEDITOR.dom.walker.nodeType = function( type, isReject )
+ {
+ return function( node )
+ {
+ return !! ( isReject ^ ( node.type == type ) );
+ };
+ };
+
+ CKEDITOR.dom.walker.bogus = function( isReject )
+ {
+ function nonEmpty( node )
+ {
+ return !isWhitespaces( node ) && !isBookmark( node );
+ }
+
+ return function( node )
+ {
+ var isBogus = !CKEDITOR.env.ie ? node.is && node.is( 'br' ) :
+ node.getText && tailNbspRegex.test( node.getText() );
+
+ if ( isBogus )
+ {
+ var parent = node.getParent(), next = node.getNext( nonEmpty );
+ isBogus = parent.isBlockBoundary() &&
+ ( !next ||
+ next.type == CKEDITOR.NODE_ELEMENT &&
+ next.isBlockBoundary() );
+ }
+
+ return !! ( isReject ^ isBogus );
};
};
var tailNbspRegex = /^[\t\r\n ]*(?: |\xa0)$/,
- isNotWhitespaces = CKEDITOR.dom.walker.whitespaces( 1 ),
- isNotBookmark = CKEDITOR.dom.walker.bookmark( 0, 1 ),
- fillerEvaluator = function( element )
+ isWhitespaces = CKEDITOR.dom.walker.whitespaces(),
+ isBookmark = CKEDITOR.dom.walker.bookmark(),
+ toSkip = function( node )
{
- return isNotBookmark( element ) && isNotWhitespaces( element );
+ return isBookmark( node )
+ || isWhitespaces( node )
+ || node.type == CKEDITOR.NODE_ELEMENT
+ && node.getName() in CKEDITOR.dtd.$inline
+ && !( node.getName() in CKEDITOR.dtd.$empty );
};
// Check if there's a filler node at the end of an element, and return it.
CKEDITOR.dom.element.prototype.getBogus = function()
{
- var tail = this.getLast( fillerEvaluator );
+ // Bogus are not always at the end, e.g.