Ticket #6438: 6438_4.patch

File 6438_4.patch, 5.4 KB (added by Garry Yao, 9 years ago)
  • _source/plugins/selection/plugin.js

     
    556556                        var func = CKEDITOR.env.ie ?
    557557                                ( function()
    558558                                {
     559                                        function getNodeIndex( node ) { return new CKEDITOR.dom.node( node ).getIndex(); }
     560
    559561                                        // Finds the container and offset for a specific boundary
    560562                                        // of an IE range.
    561563                                        var getBoundaryInformation = function( range, start )
     
    566568
    567569                                                // Gets the element that encloses the range entirely.
    568570                                                var parent = range.parentElement();
    569                                                 var siblings = parent.childNodes;
    570571
    571                                                 var testRange;
     572                                                if ( !parent.hasChildNodes() )
     573                                                        return  { container : parent, offset : 0 };
    572574
    573                                                 for ( var i = 0 ; i < siblings.length ; i++ )
    574                                                 {
    575                                                         var child = siblings[ i ];
    576                                                         if ( child.nodeType == 1 )
    577                                                         {
    578                                                                 testRange = range.duplicate();
     575                                                var siblings = parent.children,
     576                                                                child,
     577                                                                testRange = range.duplicate(),
     578                                                                startIndex = 0, endIndex = siblings.length - 1, index = -1,
     579                                                                position,
     580                                                                distance;
    579581
    580                                                                 testRange.moveToElementText( child );
     582                                                while ( startIndex <= endIndex )
     583                                                {
     584                                                        index = Math.floor( ( startIndex + endIndex ) / 2 );
     585                                                        child = siblings[ index ];
     586                                                        testRange.moveToElementText( child );
     587                                                        position = testRange.compareEndPoints( 'StartToStart', range );
    581588
    582                                                                 var comparisonStart = testRange.compareEndPoints( 'StartToStart', range ),
    583                                                                         comparisonEnd = testRange.compareEndPoints( 'EndToStart', range );
    584 
    585                                                                 testRange.collapse();
    586 
    587                                                                 if ( comparisonStart > 0 )
    588                                                                         break;
    589                                                                 // When selection stay at the side of certain self-closing elements, e.g. BR,
    590                                                                 // our comparison will never shows an equality. (#4824)
    591                                                                 else if ( !comparisonStart
    592                                                                         || comparisonEnd == 1 && comparisonStart == -1 )
    593                                                                         return { container : parent, offset : i };
    594                                                                 else if ( !comparisonEnd )
    595                                                                         return { container : parent, offset : i + 1 };
    596 
    597                                                                 testRange = null;
    598                                                         }
    599                                                 }
     589                                                        if ( position > 0 )
     590                                                                endIndex = index - 1;
     591                                                        else if ( position < 0 )
     592                                                                startIndex = index + 1;
     593                                                        else
     594                                                                return { container : parent, offset : getNodeIndex( child ) };
     595                                                }
    600596
    601                                                 if ( !testRange )
     597                                                // All childs are text nodes.
     598                                                if ( index == -1 )
    602599                                                {
    603                                                         testRange = range.duplicate();
    604600                                                        testRange.moveToElementText( parent );
    605                                                         testRange.collapse( false );
    606                                                 }
     601                                                        testRange.setEndPoint( 'StartToStart', range );
     602                                                        // IE report line break as CRLF with range.text but
     603                                                        // only LF with textnode.nodeValue, normalize them to avoid
     604                                                        // breaking character counting logic below. (#3949)
     605                                                        distance = testRange.text.replace( /(\r\n|\r)/g, '\n' ).length;
     606                                                        siblings = parent.childNodes;
     607                                                        if ( !distance )
     608                                                        {
     609                                                                child = siblings[ siblings.length - 1 ];
     610                                                                return  { container : child, offset : child.nodeValue.length };
     611                                                        }
    607612
    608                                                 testRange.setEndPoint( 'StartToStart', range );
    609                                                 // IE report line break as CRLF with range.text but
    610                                                 // only LF with textnode.nodeValue, normalize them to avoid
    611                                                 // breaking character counting logic below. (#3949)
    612                                                 var distance = testRange.text.replace( /(\r\n|\r)/g, '\n' ).length;
     613                                                        var i = siblings.length;
     614                                                        while ( distance > 0 )
     615                                                                distance -= siblings[ --i ].nodeValue.length;
     616                                                        return  { container : siblings[ i ], offset : -distance };
     617                                                }
     618                                                // Test range far from the right OR left hand side of the actual range.
     619                                                else
     620                                                {
     621                                                        testRange.collapse( position > 0 ? true : false );
     622                                                        testRange.setEndPoint( position > 0 ? 'StartToStart' : 'EndToStart', range );
     623                                                        // IE report line break as CRLF with range.text but
     624                                                        // only LF with textnode.nodeValue, normalize them to avoid
     625                                                        // breaking character counting logic below. (#3949)
     626                                                        distance = testRange.text.replace( /(\r\n|\r)/g, '\n' ).length;
    613627
    614                                                 try
    615                                                 {
    616                                                         while ( distance > 0 )
    617                                                                 distance -= siblings[ --i ].nodeValue.length;
    618                                                 }
    619                                                 // Measurement in IE could be somtimes wrong because of <select> element. (#4611)
    620                                                 catch( e )
    621                                                 {
    622                                                         distance = 0;
    623                                                 }
     628                                                        if ( !distance )
     629                                                                return { container : parent, offset : getNodeIndex( child ) + ( position > 0 ? -1 : 1 ) };
     630
     631                                                        while ( distance > 0 )
     632                                                        {
     633                                                                child = child[ position > 0 ? 'previousSibling' : 'nextSibling' ];
     634                                                                try
     635                                                                {
     636                                                                        distance -= child.nodeValue.length;
     637                                                                }
     638                                                                // Measurement in IE could be somtimes wrong because of <select> element. (#4611)
     639                                                                catch( e )
     640                                                                {
     641                                                                        return { container : parent, offset : getNodeIndex( child ) };
     642                                                                }
     643                                                        }
    624644
    625 
    626                                                 if ( distance === 0 )
    627                                                 {
    628                                                         return {
    629                                                                 container : parent,
    630                                                                 offset : i
    631                                                         };
     645                                                        return { container : child, offset : position > 0 ? -distance : child.nodeValue.length + distance };
    632646                                                }
    633                                                 else
    634                                                 {
    635                                                         return {
    636                                                                 container : siblings[ i ],
    637                                                                 offset : -distance
    638                                                         };
    639                                                 }
    640                                         };
     647                                        };
    641648
    642649                                        return function()
    643650                                        {
© 2003 – 2019 CKSource – Frederico Knabben. All rights reserved. | Terms of use | Privacy policy