X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=_source%2Fcore%2Fdom%2Frange.js;h=30a78c4b31e83ba1b70deab99fa633533ec8f1ee;hb=refs%2Ftags%2Fv3.6.3;hp=477197ef053ced2de6cf8cd9d9a66d0be11bf83e;hpb=4e70ea24db840898be8cc21c950363a52a2a6aba;p=ckeditor.git diff --git a/_source/core/dom/range.js b/_source/core/dom/range.js index 477197e..30a78c4 100644 --- a/_source/core/dom/range.js +++ b/_source/core/dom/range.js @@ -1,5 +1,5 @@ /* -Copyright (c) 2003-2011, CKSource - Frederico Knabben. All rights reserved. +Copyright (c) 2003-2012, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.html or http://ckeditor.com/license */ @@ -380,16 +380,23 @@ CKEDITOR.dom.range = function( document ) }; } + + var isBogus = CKEDITOR.dom.walker.bogus(); // Evaluator for CKEDITOR.dom.element::checkBoundaryOfElement, reject any // text node and non-empty elements unless it's being bookmark text. - function elementBoundaryEval( node ) + function elementBoundaryEval( checkStart ) { - // Reject any text node unless it's being bookmark - // OR it's spaces. (#3883) - return node.type != CKEDITOR.NODE_TEXT - && node.getName() in CKEDITOR.dtd.$removeEmpty - || !CKEDITOR.tools.trim( node.getText() ) - || !!node.getParent().data( 'cke-bookmark' ); + return function( node ) + { + // 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 ); + }; } var whitespaceEval = new CKEDITOR.dom.walker.whitespaces(), @@ -1014,7 +1021,12 @@ CKEDITOR.dom.range = function( document ) // whitespaces at the end. isWhiteSpace = false; - if ( sibling.type == CKEDITOR.NODE_TEXT ) + if ( sibling.type == CKEDITOR.NODE_COMMENT ) + { + sibling = sibling.getPrevious(); + continue; + } + else if ( sibling.type == CKEDITOR.NODE_TEXT ) { siblingText = sibling.getText(); @@ -1044,7 +1056,7 @@ CKEDITOR.dom.range = function( document ) sibling = null; else { - var allChildren = sibling.$.all || sibling.$.getElementsByTagName( '*' ); + var allChildren = sibling.$.getElementsByTagName( '*' ); for ( var i = 0, child ; child = allChildren[ i++ ] ; ) { if ( !CKEDITOR.dtd.$removeEmpty[ child.nodeName.toLowerCase() ] ) @@ -1183,7 +1195,7 @@ CKEDITOR.dom.range = function( document ) isWhiteSpace = /^[\s\ufeff]/.test( siblingText ); } - else + else if ( sibling.type == CKEDITOR.NODE_ELEMENT ) { // If this is a visible element. // We need to check for the bookmark attribute because IE insists on @@ -1204,7 +1216,7 @@ CKEDITOR.dom.range = function( document ) sibling = null; else { - allChildren = sibling.$.all || sibling.$.getElementsByTagName( '*' ); + allChildren = sibling.$.getElementsByTagName( '*' ); for ( i = 0 ; child = allChildren[ i++ ] ; ) { if ( !CKEDITOR.dtd.$removeEmpty[ child.nodeName.toLowerCase() ] ) @@ -1222,6 +1234,8 @@ CKEDITOR.dom.range = function( document ) sibling = null; } } + else + isWhiteSpace = 1; if ( isWhiteSpace ) { @@ -1320,6 +1334,22 @@ CKEDITOR.dom.range = function( document ) CKEDITOR.POSITION_AFTER_START : CKEDITOR.POSITION_AFTER_END ); + // Avoid enlarging the range further when end boundary spans right after the BR. (#7490) + if ( unit == CKEDITOR.ENLARGE_LIST_ITEM_CONTENTS ) + { + var theRange = this.clone(); + walker = new CKEDITOR.dom.walker( theRange ); + + var whitespaces = CKEDITOR.dom.walker.whitespaces(), + bookmark = CKEDITOR.dom.walker.bookmark(); + + walker.evaluator = function( node ) { return !whitespaces( node ) && !bookmark( node ); }; + var previous = walker.previous(); + if ( previous && previous.type == CKEDITOR.NODE_ELEMENT && previous.is( 'br' ) ) + return; + } + + // Enlarging the end boundary. walkerRange = this.clone(); walkerRange.collapse(); @@ -1777,7 +1807,7 @@ CKEDITOR.dom.range = function( document ) // Create the walker, which will check if we have anything useful // in the range. var walker = new CKEDITOR.dom.walker( walkerRange ); - walker.evaluator = elementBoundaryEval; + walker.evaluator = elementBoundaryEval( checkStart ); return walker[ checkStart ? 'checkBackward' : 'checkForward' ](); }, @@ -1904,47 +1934,53 @@ CKEDITOR.dom.range = function( document ) */ moveToElementEditablePosition : function( el, isMoveToEnd ) { - var isEditable; - - // Empty elements are rejected. - if ( CKEDITOR.dtd.$empty[ el.getName() ] ) - return false; - - while ( el && el.type == CKEDITOR.NODE_ELEMENT ) + function nextDFS( node, childOnly ) { - isEditable = el.isEditable(); + var next; - // If an editable element is found, move inside it. - if ( isEditable ) - this.moveToPosition( el, isMoveToEnd ? - CKEDITOR.POSITION_BEFORE_END : - CKEDITOR.POSITION_AFTER_START ); - // Stop immediately if we've found a non editable inline element (e.g ). - else if ( CKEDITOR.dtd.$inline[ el.getName() ] ) + if ( node.type == CKEDITOR.NODE_ELEMENT + && node.isEditable( false ) + && !CKEDITOR.dtd.$nonEditable[ node.getName() ] ) { - this.moveToPosition( el, isMoveToEnd ? - CKEDITOR.POSITION_AFTER_END : - CKEDITOR.POSITION_BEFORE_START ); - return true; + next = node[ isMoveToEnd ? 'getLast' : 'getFirst' ]( nonWhitespaceOrBookmarkEval ); } - // Non-editable non-inline elements are to be bypassed, getting the next one. - if ( CKEDITOR.dtd.$empty[ el.getName() ] ) - el = el[ isMoveToEnd ? 'getPrevious' : 'getNext' ]( nonWhitespaceOrBookmarkEval ); - else - el = el[ isMoveToEnd ? 'getLast' : 'getFirst' ]( nonWhitespaceOrBookmarkEval ); + if ( !childOnly && !next ) + next = node[ isMoveToEnd ? 'getPrevious' : 'getNext' ]( nonWhitespaceOrBookmarkEval ); + return next; + } + + var found = 0; + + while ( el ) + { // Stop immediately if we've found a text node. - if ( el && el.type == CKEDITOR.NODE_TEXT ) + if ( el.type == CKEDITOR.NODE_TEXT ) { this.moveToPosition( el, isMoveToEnd ? CKEDITOR.POSITION_AFTER_END : CKEDITOR.POSITION_BEFORE_START ); - return true; + found = 1; + break; + } + + // If an editable element is found, move inside it, but not stop the searching. + if ( el.type == CKEDITOR.NODE_ELEMENT ) + { + if ( el.isEditable() ) + { + this.moveToPosition( el, isMoveToEnd ? + CKEDITOR.POSITION_BEFORE_END : + CKEDITOR.POSITION_AFTER_START ); + found = 1; + } } + + el = nextDFS( el, found ); } - return isEditable; + return !!found; }, /**