Ticket #3240: 3240_3.patch

File 3240_3.patch, 6.2 KB (added by Garry Yao, 11 years ago)
  • core/dom/node.js

     
    413413
    414414                getPosition : function( otherNode )
    415415                {
    416                         var $ = this.$;
    417                         var $other = otherNode.$;
     416                        function standard( a, b ){
     417                                return a.compareDocumentPosition ?
     418                                       a.compareDocumentPosition( b ) :
     419                                       a.contains ?
     420                                       ( a != b && a.contains( b ) && CKEDITOR.POSITION_CONTAINS ) +
     421                                       ( a != b && b.contains( a ) && CKEDITOR.POSITION_IS_CONTAINED ) +
     422                                       ( a.sourceIndex >= 0 && b.sourceIndex >= 0 ?
     423                                        ( a.sourceIndex < b.sourceIndex && CKEDITOR.POSITION_PRECEDING ) +
     424                                        ( a.sourceIndex > b.sourceIndex && CKEDITOR.POSITION_FOLLOWING ) :
     425                                        CKEDITOR.POSITION_DISCONNECTED ) +
     426                                       CKEDITOR.POSITION_IDENTICAL :
     427                                       CKEDITOR.POSITION_IDENTICAL;
     428                        }
    418429
    419                         if ( $.compareDocumentPosition )
    420                                 return $.compareDocumentPosition( $other );
    421 
    422                         // IE and Safari have no support for compareDocumentPosition.
    423 
    424                         if ( $ == $other )
    425                                 return CKEDITOR.POSITION_IDENTICAL;
    426 
    427                         // Handle non element nodes (don't support contains nor sourceIndex).
    428                         if ( this.type != CKEDITOR.NODE_ELEMENT || otherNode.type != CKEDITOR.NODE_ELEMENT )
     430                        var hasSupportOn = CKEDITOR.env.support.compareDocumentPositionOn;
     431                        if ( hasSupportOn( this ) && hasSupportOn( otherNode ) )
     432                                return standard( this.$, otherNode.$ );
     433                        else
    429434                        {
    430                                 if ( $.parentNode == $other )
    431                                         return CKEDITOR.POSITION_IS_CONTAINED + CKEDITOR.POSITION_FOLLOWING;
    432                                 else if ( $other.parentNode == $ )
    433                                         return CKEDITOR.POSITION_CONTAINS + CKEDITOR.POSITION_PRECEDING;
    434                                 else if ( $.parentNode == $other.parentNode )
    435                                         return this.getIndex() < otherNode.getIndex() ? CKEDITOR.POSITION_PRECEDING : CKEDITOR.POSITION_FOLLOWING;
    436                                 else
     435                                var addressOfThis = this.getAddress(),
     436                                        addressOfOther = otherNode.getAddress(),
     437                                        minLevel = Math.min( addressOfThis.length, addressOfOther.length ),
     438                                        maxLevel = Math.max ( addressOfThis.length, addressOfOther.length  ),
     439                                        position = 0;
     440
     441                                // Determinate preceed/follow relationship.
     442                                for ( var i = 0; i <= minLevel - 1 ; i++ )
    437443                                {
    438                                         $ = $.parentNode;
    439                                         $other = $other.parentNode;
     444                                        if ( addressOfThis[ i ] != addressOfOther[ i ] )
     445                                        {
     446                                                position = addressOfThis[ i ] < addressOfOther[ i ] ?
     447                                                            CKEDITOR.POSITION_PRECEDING : CKEDITOR.POSITION_FOLLOWING;
     448                                                break;
     449                                        }
    440450                                }
    441                         }
    442451
    443                         if ( $.contains( $other ) )
    444                                 return CKEDITOR.POSITION_CONTAINS + CKEDITOR.POSITION_PRECEDING;
    445 
    446                         if ( $other.contains( $ ) )
    447                                 return CKEDITOR.POSITION_IS_CONTAINED + CKEDITOR.POSITION_FOLLOWING;
    448 
    449                         if ( 'sourceIndex' in $ )
    450                         {
    451                                 return ( $.sourceIndex < 0 || $other.sourceIndex < 0 ) ? CKEDITOR.POSITION_DISCONNECTED :
    452                                         ( $.sourceIndex < $other.sourceIndex ) ? CKEDITOR.POSITION_PRECEDING :
    453                                         CKEDITOR.POSITION_FOLLOWING;
     452                                // Determinate contains/contained relationship.
     453                                position = ( i < minLevel ) ? position :
     454                                                    ( minLevel == maxLevel ? CKEDITOR.POSITION_IDENTICAL :
     455                                                                                ( addressOfThis.length < addressOfOther.length ?
     456                                                                                        CKEDITOR.POSITION_CONTAINS + CKEDITOR.POSITION_PRECEDING :
     457                                                                                        CKEDITOR.POSITION_IS_CONTAINED + CKEDITOR.POSITION_FOLLOWING ) );
     458                                return position;
    454459                        }
    455 
    456                         // WebKit has no support for sourceIndex.
    457 
    458                         var doc = this.getDocument().$;
    459 
    460                         var range1 = doc.createRange();
    461                         var range2 = doc.createRange();
    462 
    463                         range1.selectNode( $ );
    464                         range2.selectNode( $other );
    465 
    466                         return range1.compareBoundaryPoints( 1, range2 ) > 0 ?
    467                                 CKEDITOR.POSITION_FOLLOWING :
    468                                 CKEDITOR.POSITION_PRECEDING;
    469460                },
    470461
    471462                /**
  • core/env.js

     
    192192                if ( env.gecko && version < 10900 )
    193193                        env.cssClass += ' cke_browser_gecko18';
    194194
     195                // Feature detections below for capabilities of certain native API
     196                // we rely on.
     197                env.support =
     198                {
     199                        //1. DOMNode.compareDocumentPosition is completely available in Firefox and Opera.
     200                        //2. IE doesn't support .contains() and .sourceIndex property on any DOM element type node.
     201                        //3. Webkit support only .contains() but no .sourceIndex.
     202                        compareDocumentPositionOn : function( node )
     203                        {
     204                                return env.gecko || env.opera || ( env.ie && node.type == CKEDITOR.NODE_ELEMENT );
     205                        }
     206                };
    195207                return env;
    196208        })();
    197209}
  • tests/core/dom/node.html

     
    99        <script type="text/javascript" src="../../test.js"></script>
    1010        <script type="text/javascript">
    1111        //<![CDATA[
    12 
    13 CKEDITOR.test.addTestCase( (function()
     12var tc;
     13CKEDITOR.test.addTestCase( tc = (function()
    1414{
    1515        // Local reference to the "assert" object.
    1616        var assert = CKEDITOR.test.assert;
     
    6868                {
    6969                        var node1 = new CKEDITOR.dom.node( document.getElementsByTagName( 'h1' )[0] );
    7070                        var node2 = new CKEDITOR.dom.node( document.getElementsByTagName( 'h1' )[0].firstChild );
    71 
    7271                        assert.areSame( CKEDITOR.POSITION_IS_CONTAINED + CKEDITOR.POSITION_FOLLOWING, node2.getPosition( node1 ) );
    7372                },
    7473
     
    104103                        assert.areSame( CKEDITOR.POSITION_FOLLOWING, node2.getPosition( node1 ) );
    105104                },
    106105
     106                /**
     107                 *  Test 'preceding' position.
     108                 */
     109                test_getPosition_3240: function()
     110                {
     111                        var node1 = new CKEDITOR.dom.node( document.getElementsByTagName( 'b' )[0].firstChild );
     112                        var node2 = new CKEDITOR.dom.node( document.getElementsByTagName( 'span' )[0].firstChild );
     113
     114                        assert.areSame( CKEDITOR.POSITION_PRECEDING, node1.getPosition( node2 ) );
     115                },
     116
    107117                name : document.title
    108118        };
    109119})() );
     
    115125//
    116126//      alert( node1.getPosition( node2 ) );
    117127//};
    118 
     128//window.onload =  tc.test_getPosition6;
    119129        //]]>
    120130        </script>
    121131</head>
     
    124134                <h1>Title</h1>
    125135                <p><b>Sample</b> <i>Text</i></p>
    126136        </div>
     137        <span>Another</span>
    127138</body>
    128139</html>
© 2003 – 2019 CKSource – Frederico Knabben. All rights reserved. | Terms of use | Privacy policy