X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=_source%2Fcore%2Fdom%2Frange.js;h=fbbbe357f1b48d368dca10fa21a148fac4184002;hb=a272c66d841421f8bf933c16535bdcde1c4649fc;hp=c8312b749b3008e1b304afd3e45c587104c06880;hpb=6e682412d5cc0dfaedb376482e585bf2989c6863;p=ckeditor.git
diff --git a/_source/core/dom/range.js b/_source/core/dom/range.js
index c8312b7..fbbbe35 100644
--- a/_source/core/dom/range.js
+++ b/_source/core/dom/range.js
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2003-2012, 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
*/
@@ -347,50 +347,38 @@ CKEDITOR.dom.range = function( document )
// Creates the appropriate node evaluator for the dom walker used inside
// check(Start|End)OfBlock.
- function getCheckStartEndBlockEvalFunction( isStart )
+ function getCheckStartEndBlockEvalFunction()
{
var skipBogus = false,
+ whitespaces = CKEDITOR.dom.walker.whitespaces(),
bookmarkEvaluator = CKEDITOR.dom.walker.bookmark( true ),
- nbspRegExp = /^[\t\r\n ]*(?: |\xa0)$/;
+ isBogus = CKEDITOR.dom.walker.bogus();
return function( node )
{
- // First ignore bookmark nodes.
- if ( bookmarkEvaluator( node ) )
+ // First skip empty nodes.
+ if ( bookmarkEvaluator( node ) || whitespaces( node ) )
return true;
- if ( node.type == CKEDITOR.NODE_TEXT )
+ // Skip the bogus node at the end of block.
+ if ( isBogus( node ) &&
+ !skipBogus )
{
- // Skip the block filler NBSP.
- if ( CKEDITOR.env.ie &&
- nbspRegExp.test( node.getText() ) &&
- !skipBogus &&
- !( isStart && node.getNext() ) )
- {
- skipBogus = true;
- }
- // If there's any visible text, then we're not at the start.
- else if ( node.hasAscendant( 'pre' ) || CKEDITOR.tools.trim( node.getText() ).length )
- return false;
- }
- else if ( node.type == CKEDITOR.NODE_ELEMENT )
- {
- // If there are non-empty inline elements (e.g. ), then we're not
- // at the start.
- if ( !inlineChildReqElements[ node.getName() ] )
- {
- // Skip the padding block br.
- if ( !CKEDITOR.env.ie &&
- node.is( 'br' ) &&
- !skipBogus &&
- !( isStart && node.getNext() ) )
- {
- skipBogus = true;
- }
- else
- return false;
- }
+ skipBogus = true;
+ return true;
}
+
+ // If there's any visible text, then we're not at the start.
+ if ( node.type == CKEDITOR.NODE_TEXT &&
+ ( node.hasAscendant( 'pre' ) ||
+ CKEDITOR.tools.trim( node.getText() ).length ) )
+ return false;
+
+ // If there are non-empty inline elements (e.g. ), then we're not
+ // at the start.
+ if ( node.type == CKEDITOR.NODE_ELEMENT && !inlineChildReqElements[ node.getName() ] )
+ return false;
+
return true;
};
}
@@ -401,21 +389,28 @@ CKEDITOR.dom.range = function( document )
// text node and non-empty elements unless it's being bookmark text.
function elementBoundaryEval( checkStart )
{
+ var whitespaces = CKEDITOR.dom.walker.whitespaces(),
+ bookmark = CKEDITOR.dom.walker.bookmark( 1 );
+
return function( node )
{
+ // First skip empty nodes.
+ if ( bookmark( node ) || whitespaces( node ) )
+ return true;
+
// Tolerant bogus br when checking at the end of block.
// Reject any text node unless it's being bookmark
// OR it's spaces.
// Reject any element unless it's being invisible empty. (#3883)
return !checkStart && isBogus( node ) ||
- ( node.type == CKEDITOR.NODE_TEXT ?
- !CKEDITOR.tools.trim( node.getText() ) || !!node.getParent().data( 'cke-bookmark' )
- : node.getName() in CKEDITOR.dtd.$removeEmpty );
+ node.type == CKEDITOR.NODE_ELEMENT &&
+ node.getName() in CKEDITOR.dtd.$removeEmpty;
};
}
var whitespaceEval = new CKEDITOR.dom.walker.whitespaces(),
- bookmarkEval = new CKEDITOR.dom.walker.bookmark();
+ bookmarkEval = new CKEDITOR.dom.walker.bookmark(),
+ nbspRegExp = /^[\t\r\n ]*(?: |\xa0)$/;
function nonWhitespaceOrBookmarkEval( node )
{
@@ -1834,13 +1829,13 @@ CKEDITOR.dom.range = function( document )
var startContainer = this.startContainer,
startOffset = this.startOffset;
- // If the starting node is a text node, and non-empty before the offset,
- // then we're surely not at the start of block.
- if ( startOffset && startContainer.type == CKEDITOR.NODE_TEXT )
+ // [IE] Special handling for range start in text with a leading NBSP,
+ // we it to be isolated, for bogus check.
+ if ( CKEDITOR.env.ie && startOffset && startContainer.type == CKEDITOR.NODE_TEXT )
{
var textBefore = CKEDITOR.tools.ltrim( startContainer.substring( 0, startOffset ) );
- if ( textBefore.length )
- return false;
+ if ( nbspRegExp.test( textBefore ) )
+ this.trim( 0, 1 );
}
// We need to grab the block element holding the start boundary, so
@@ -1853,7 +1848,7 @@ CKEDITOR.dom.range = function( document )
walkerRange.setStartAt( path.block || path.blockLimit, CKEDITOR.POSITION_AFTER_START );
var walker = new CKEDITOR.dom.walker( walkerRange );
- walker.evaluator = getCheckStartEndBlockEvalFunction( true );
+ walker.evaluator = getCheckStartEndBlockEvalFunction();
return walker.checkBackward();
},
@@ -1863,13 +1858,13 @@ CKEDITOR.dom.range = function( document )
var endContainer = this.endContainer,
endOffset = this.endOffset;
- // If the ending node is a text node, and non-empty after the offset,
- // then we're surely not at the end of block.
- if ( endContainer.type == CKEDITOR.NODE_TEXT )
+ // [IE] Special handling for range end in text with a following NBSP,
+ // we it to be isolated, for bogus check.
+ if ( CKEDITOR.env.ie && endContainer.type == CKEDITOR.NODE_TEXT )
{
var textAfter = CKEDITOR.tools.rtrim( endContainer.substring( endOffset ) );
- if ( textAfter.length )
- return false;
+ if ( nbspRegExp.test( textAfter ) )
+ this.trim( 1, 0 );
}
// We need to grab the block element holding the start boundary, so
@@ -1882,15 +1877,53 @@ CKEDITOR.dom.range = function( document )
walkerRange.setEndAt( path.block || path.blockLimit, CKEDITOR.POSITION_BEFORE_END );
var walker = new CKEDITOR.dom.walker( walkerRange );
- walker.evaluator = getCheckStartEndBlockEvalFunction( false );
+ walker.evaluator = getCheckStartEndBlockEvalFunction();
return walker.checkForward();
},
/**
- * Check if elements at which the range boundaries anchor are read-only,
- * with respect to "contenteditable" attribute.
+ * Traverse with {@link CKEDITOR.dom.walker} to retrieve the previous element before the range start.
+ * @param {Function} evaluator Function used as the walker's evaluator.
+ * @param {Function} [guard] Function used as the walker's guard.
+ * @param {CKEDITOR.dom.element} [boundary] A range ancestor element in which the traversal is limited,
+ * default to the root editable if not defined.
+ *
+ * @return {CKEDITOR.dom.element|null} The returned node from the traversal.
+ */
+ getPreviousNode : function( evaluator, guard, boundary ) {
+
+ var walkerRange = this.clone();
+ walkerRange.collapse( 1 );
+ walkerRange.setStartAt( boundary || this.document.getBody(), CKEDITOR.POSITION_AFTER_START );
+
+ var walker = new CKEDITOR.dom.walker( walkerRange );
+ walker.evaluator = evaluator;
+ walker.guard = guard;
+ return walker.previous();
+ },
+
+ /**
+ * Traverse with {@link CKEDITOR.dom.walker} to retrieve the next element before the range start.
+ * @param {Function} evaluator Function used as the walker's evaluator.
+ * @param {Function} [guard] Function used as the walker's guard.
+ * @param {CKEDITOR.dom.element} [boundary] A range ancestor element in which the traversal is limited,
+ * default to the root editable if not defined.
+ *
+ * @return {CKEDITOR.dom.element|null} The returned node from the traversal.
*/
+ getNextNode: function( evaluator, guard, boundary )
+ {
+ var walkerRange = this.clone();
+ walkerRange.collapse();
+ walkerRange.setEndAt( boundary || this.document.getBody(), CKEDITOR.POSITION_BEFORE_END );
+
+ var walker = new CKEDITOR.dom.walker( walkerRange );
+ walker.evaluator = evaluator;
+ walker.guard = guard;
+ return walker.next();
+ },
+
checkReadOnly : ( function()
{
function checkNodesEditable( node, anotherEnd )
@@ -1939,8 +1972,6 @@ CKEDITOR.dom.range = function( document )
*/
moveToElementEditablePosition : function( el, isMoveToEnd )
{
- var nbspRegExp = /^[\t\r\n ]*(?: |\xa0)$/;
-
function nextDFS( node, childOnly )
{
var next;