Index: core/dom/node.js =================================================================== --- core/dom/node.js (revision 3504) +++ core/dom/node.js (working copy) @@ -413,59 +413,50 @@ getPosition : function( otherNode ) { - var $ = this.$; - var $other = otherNode.$; + function standard( a, b ){ + return a.compareDocumentPosition ? + a.compareDocumentPosition( b ) : + a.contains ? + ( a != b && a.contains( b ) && CKEDITOR.POSITION_CONTAINS ) + + ( a != b && b.contains( a ) && CKEDITOR.POSITION_IS_CONTAINED ) + + ( a.sourceIndex >= 0 && b.sourceIndex >= 0 ? + ( a.sourceIndex < b.sourceIndex && CKEDITOR.POSITION_PRECEDING ) + + ( a.sourceIndex > b.sourceIndex && CKEDITOR.POSITION_FOLLOWING ) : + CKEDITOR.POSITION_DISCONNECTED ) + + CKEDITOR.POSITION_IDENTICAL : + CKEDITOR.POSITION_IDENTICAL; + } - if ( $.compareDocumentPosition ) - return $.compareDocumentPosition( $other ); - - // IE and Safari have no support for compareDocumentPosition. - - if ( $ == $other ) - return CKEDITOR.POSITION_IDENTICAL; - - // Handle non element nodes (don't support contains nor sourceIndex). - if ( this.type != CKEDITOR.NODE_ELEMENT || otherNode.type != CKEDITOR.NODE_ELEMENT ) + var hasSupportOn = CKEDITOR.env.support.compareDocumentPositionOn; + if ( hasSupportOn( this ) && hasSupportOn( otherNode ) ) + return standard( this.$, otherNode.$ ); + else { - if ( $.parentNode == $other ) - return CKEDITOR.POSITION_IS_CONTAINED + CKEDITOR.POSITION_FOLLOWING; - else if ( $other.parentNode == $ ) - return CKEDITOR.POSITION_CONTAINS + CKEDITOR.POSITION_PRECEDING; - else if ( $.parentNode == $other.parentNode ) - return this.getIndex() < otherNode.getIndex() ? CKEDITOR.POSITION_PRECEDING : CKEDITOR.POSITION_FOLLOWING; - else + var addressOfThis = this.getAddress(), + addressOfOther = otherNode.getAddress(), + minLevel = Math.min( addressOfThis.length, addressOfOther.length ), + maxLevel = Math.max ( addressOfThis.length, addressOfOther.length ), + position = 0; + + // Determinate preceed/follow relationship. + for ( var i = 0; i <= minLevel - 1 ; i++ ) { - $ = $.parentNode; - $other = $other.parentNode; + if ( addressOfThis[ i ] != addressOfOther[ i ] ) + { + position = addressOfThis[ i ] < addressOfOther[ i ] ? + CKEDITOR.POSITION_PRECEDING : CKEDITOR.POSITION_FOLLOWING; + break; + } } - } - if ( $.contains( $other ) ) - return CKEDITOR.POSITION_CONTAINS + CKEDITOR.POSITION_PRECEDING; - - if ( $other.contains( $ ) ) - return CKEDITOR.POSITION_IS_CONTAINED + CKEDITOR.POSITION_FOLLOWING; - - if ( 'sourceIndex' in $ ) - { - return ( $.sourceIndex < 0 || $other.sourceIndex < 0 ) ? CKEDITOR.POSITION_DISCONNECTED : - ( $.sourceIndex < $other.sourceIndex ) ? CKEDITOR.POSITION_PRECEDING : - CKEDITOR.POSITION_FOLLOWING; + // Determinate contains/contained relationship. + position = ( i < minLevel ) ? position : + ( minLevel == maxLevel ? CKEDITOR.POSITION_IDENTICAL : + ( addressOfThis.length < addressOfOther.length ? + CKEDITOR.POSITION_CONTAINS + CKEDITOR.POSITION_PRECEDING : + CKEDITOR.POSITION_IS_CONTAINED + CKEDITOR.POSITION_FOLLOWING ) ); + return position; } - - // WebKit has no support for sourceIndex. - - var doc = this.getDocument().$; - - var range1 = doc.createRange(); - var range2 = doc.createRange(); - - range1.selectNode( $ ); - range2.selectNode( $other ); - - return range1.compareBoundaryPoints( 1, range2 ) > 0 ? - CKEDITOR.POSITION_FOLLOWING : - CKEDITOR.POSITION_PRECEDING; }, /** Index: core/env.js =================================================================== --- core/env.js (revision 3504) +++ core/env.js (working copy) @@ -192,6 +192,18 @@ if ( env.gecko && version < 10900 ) env.cssClass += ' cke_browser_gecko18'; + // Feature detections below for capabilities of certain native API + // we rely on. + env.support = + { + //1. DOMNode.compareDocumentPosition is completely available in Firefox and Opera. + //2. IE doesn't support .contains() and .sourceIndex property on any DOM element type node. + //3. Webkit support only .contains() but no .sourceIndex. + compareDocumentPositionOn : function( node ) + { + return env.gecko || env.opera || ( env.ie && node.type == CKEDITOR.NODE_ELEMENT ); + } + }; return env; })(); } Index: tests/core/dom/node.html =================================================================== --- tests/core/dom/node.html (revision 3515) +++ tests/core/dom/node.html (working copy) @@ -9,8 +9,8 @@ @@ -124,5 +134,6 @@
Sample Text
+ Another