Ticket #2150: 2150_pre.patch

File 2150_pre.patch, 20.7 KB (added by Martin Kou, 12 years ago)
  • editor/dialog/fck_replace.html

     
    3434var dialogArguments = dialog.Args() ;
    3535
    3636var FCKLang = oEditor.FCKLang ;
     37var FCKDomTools = oEditor.FCKDomTools ;
     38var FCKDomRange = oEditor.FCKDomRange ;
     39var FCKListsLib = oEditor.FCKListsLib ;
     40var FCKTools = oEditor.FCKTools ;
     41var EditorDocument = oEditor.FCK.EditorDocument ;
     42var HighlightStyle = oEditor.FCKStyles.GetStyle( '_FCK_SelectionHighlight' )  ;
    3743
    3844dialog.AddTab( 'Find', FCKLang.DlgFindTitle ) ;
    3945dialog.AddTab( 'Replace', FCKLang.DlgReplaceTitle ) ;
     
    5157                dialog.SetAutoSize( true ) ;
    5258}
    5359
    54 // Place a range at the start of document.
    55 // This will be the starting point of our search.
    56 var GlobalRange = new oEditor.FCKDomRange( oEditor.FCK.EditorWindow ) ;
    57 
    58 function ResetGlobalRange()
     60GetNextNonEmptyTextNode = function( node, stopNode )
    5961{
    60         GlobalRange.SetStart( oEditor.FCK.EditorDocument.body, 1 ) ;
    61         GlobalRange.SetEnd( oEditor.FCK.EditorDocument.body, 1 ) ;
    62         GlobalRange.Collapse( true ) ;
     62        var node ;
     63        while ( ( node = FCKDomTools.GetNextSourceNode( node, false, 3, stopNode ) ) && node && node.length < 1 ) ;
     64        return node ;
    6365}
    64 ResetGlobalRange() ;
    6566
    66 var HighlightRange = null ;
    67 function Highlight()
     67CharacterCursor = function( arg )
    6868{
    69         if ( HighlightRange )
    70                 ClearHighlight() ;
    71         var cloneRange = GlobalRange.Clone() ;
    72         oEditor.FCKStyles.GetStyle( '_FCK_SelectionHighlight' ).ApplyToRange( cloneRange, false, true ) ;
    73         HighlightRange = cloneRange ;
    74         GlobalRange = HighlightRange.Clone() ;
    75 }
    76 
    77 function ClearHighlight()
    78 {
    79         if ( HighlightRange )
     69        if ( arg.nodeType && arg.nodeType == 9 )
    8070        {
    81                 oEditor.FCKStyles.GetStyle( '_FCK_SelectionHighlight' ).RemoveFromRange( HighlightRange, false, true ) ;
    82                 HighlightRange = null ;
     71                this._textNode = GetNextNonEmptyTextNode( arg.body, arg.documentElement ) ;
     72                this._offset = 0 ;
     73                this._doc = arg ;
    8374        }
     75        else
     76        {
     77                this._textNode = arguments[0] ;
     78                this._offset = arguments[1] ;
     79                this._doc = FCKTools.GetElementDocument( arguments[0] ) ;
     80        }
    8481}
    85 
    86 function OnLoad()
     82CharacterCursor.prototype =
    8783{
    88         // First of all, translate the dialog box texts.
    89         oEditor.FCKLanguageManager.TranslatePage( document ) ;
     84        GetCharacter : function()
     85        {
     86                return ( this._textNode && this._textNode.nodeValue.charAt( this._offset ) ) || null ;
     87        },
    9088
    91         // Show the appropriate tab at startup.
    92         if ( dialogArguments.CustomValue == 'Find' )
     89        // Non-normalized.
     90        GetTextNode : function()
    9391        {
    94                 dialog.SetSelectedTab( 'Find' ) ;
    95                 dialog.SetAutoSize( true ) ;
    96         }
    97         else
    98                 dialog.SetSelectedTab( 'Replace' ) ;
     92                return this._textNode ;
     93        },
    9994
    100         SelectField( 'txtFind' + dialogArguments.CustomValue ) ;
    101 }
     95        // Non-normalized.
     96        GetIndex : function()
     97        {
     98                return this._offset ;
     99        },
    102100
    103 function btnStat()
    104 {
    105         GetE('btnReplace').disabled =
    106                 GetE('btnReplaceAll').disabled =
    107                         GetE('btnFind').disabled =
    108                                 ( GetE(idMap["FindText"]).value.length == 0 ) ;
    109 }
     101        // Normalized address ready to be put into a bookmark.
     102        GetAddress : function()
     103        {
     104                if ( !this._textNode )
     105                        return null ;
     106                var nodeAddress = FCKDomTools.GetNodeAddress( this._textNode, true ) ;
     107                var textAddress = this._offset ;
     108                var curTextNode = this._textNode ;
     109                while ( ( curTextNode = curTextNode.previousSibling ) && ( curTextNode.nodeType == 3 ) )
     110                        textAddress += curTextNode.length ;
     111                return nodeAddress.concat( [textAddress] ) ;
     112        },
    110113
    111 function btnStatDelayed()
    112 {
    113         setTimeout( btnStat, 1 ) ;
    114 }
     114        // Return value means whehther we've crossed a line break or a paragraph boundary.
     115        MoveNext : function()
     116        {
     117                if ( this._offset < this._textNode.length - 1 )
     118                {
     119                        this._offset++ ;
     120                        return false ;
     121                }
    115122
    116 function GetSearchString()
    117 {
    118         return GetE(idMap['FindText']).value ;
    119 }
     123                var crossed = false ;
     124                var curNode = this._textNode ;
     125                while ( ( curNode = FCKDomTools.GetNextSourceNode( curNode ) )
     126                                && curNode && ( curNode.nodeType != 3 || curNode.length < 1 ) )
     127                {
     128                        var tag = curNode.nodeName.toLowerCase() ;
     129                        if ( FCKListsLib.BlockElements[tag] || tag == 'br' )
     130                                crossed = true ;
     131                }
    120132
    121 function GetReplaceString()
    122 {
    123         return GetE("txtReplace").value ;
    124 }
     133                this._textNode = curNode ;
     134                this._offset = 0 ;
     135                return crossed ;
     136        },
    125137
    126 function GetCheckCase()
    127 {
    128         return !! ( GetE(idMap['CheckCase']).checked ) ;
    129 }
     138        // Return value means whehther we've crossed a line break or a paragraph boundary.
     139        MoveBack : function()
     140        {
     141                if ( this._offset > 0 && this._textNode.length > 0 )
     142                {
     143                        this._offset = Math.max( this._offset - 1, this._textNode.length - 1 ) ;
     144                        return false ;
     145                }
    130146
    131 function GetMatchWord()
     147                var crossed = false ;
     148                var curNode = this._textNode ;
     149                while ( ( curNode = FCKDomTools.GetPreviousSourceNode( curNode ) )
     150                                && curNode && ( curNode.nodeType != 3 || curNode.length < 1 ) )
     151                {
     152                        var tag = curNode.tagName.toLowerCase() ;
     153                        if ( FCKListsLib.BlockElements[tag] || tag == 'br' )
     154                                crossed = true ;
     155                }
     156
     157                this._textNode = curNode ;
     158                this._offset = 0 ;
     159                return crossed ;
     160        },
     161
     162        Clone : function()
     163        {
     164                return new CharacterCursor( this._textNode, this._offset ) ;
     165        }
     166} ;
     167
     168CharacterRange = function( initCursor, maxLength )
    132169{
    133         return !! ( GetE(idMap['CheckWord']).checked ) ;
     170        this._cursors = initCursor.push ? initCursor : [initCursor] ;
     171        this._maxLength = maxLength ;
     172        this._highlightRange = null ;
    134173}
    135 
    136 // Get the data pointed to by a bookmark.
    137 function GetData( bookmark )
     174CharacterRange.prototype =
    138175{
    139         var cursor = oEditor.FCK.EditorDocument.documentElement ;
    140         for ( var i = 0 ; i < bookmark.length ; i++ )
     176        ToDomRange : function()
    141177        {
    142                 var target = bookmark[i] ;
    143                 var currentIndex = -1 ;
    144                 if ( cursor.nodeType != 3 )
    145                 {
    146                         for (var j = 0 ; j < cursor.childNodes.length ; j++ )
    147                         {
    148                                 var candidate = cursor.childNodes[j] ;
    149                                 if ( candidate.nodeType == 3 &&
    150                                                 candidate.previousSibling &&
    151                                                 candidate.previousSibling.nodeType == 3 )
    152                                         continue ;
    153                                 currentIndex++ ;
    154                                 if ( currentIndex == target )
    155                                 {
    156                                         cursor = candidate ;
    157                                         break ;
    158                                 }
    159                         }
    160                         if ( currentIndex < target )
    161                                 return null ;
    162                 }
     178                var firstCursor = this._cursors[0] ;
     179                var lastCursor = this._cursors[ this._cursors.length - 1 ] ;
     180                var domRange = new FCKDomRange( FCKTools.GetElementWindow( firstCursor.GetTextNode() ) ) ;
     181                var w3cRange = domRange._Range = domRange.CreateRange() ;
     182                w3cRange.setStart( firstCursor.GetTextNode(), firstCursor.GetIndex() ) ;
     183                w3cRange.setEnd( lastCursor.GetTextNode(), lastCursor.GetIndex() + 1 ) ;
     184                domRange._UpdateElementInfo() ;
     185                return domRange ;
     186        },
     187
     188        Highlight : function()
     189        {
     190                if ( this._cursors.length < 1 )
     191                        return ;
     192
     193                var domRange = this.ToDomRange() ;
     194                HighlightStyle.ApplyToRange( domRange, false, true ) ;
     195                this._highlightRange = domRange ;
     196
     197                var charRange = CharacterRange.CreateFromDomRange( domRange ) ;
     198                var focusNode = domRange.StartNode ;
     199                if ( focusNode.nodeType != 1 )
     200                        focusNode = focusNode.parentNode ;
     201                if ( oEditor.FCKBrowserInfo.IsSafari )
     202                        FCKDomTools.ScrollIntoView( focusNode ) ;
    163203                else
     204                        focusNode.scrollIntoView( false ) ;
     205                this._cursors = charRange._cursors ;
     206        },
     207
     208        RemoveHighlight : function()
     209        {
     210                if ( this._highlightRange )
    164211                {
    165                         if ( i != bookmark.length - 1 )
    166                                 return null ;
    167                         while ( target >= cursor.length && cursor.nextSibling && cursor.nextSibling.nodeType == 3 )
    168                         {
    169                                 target -= cursor.length ;
    170                                 cursor = cursor.nextSibling ;
    171                         }
    172                         cursor = cursor.nodeValue.charAt( target ) ;
    173                         if ( cursor == "" )
    174                                 cursor = null ;
     212                        HighlightStyle.RemoveFromRange( this._highlightRange, false, true ) ;
     213                        var charRange = CharacterRange.CreateFromDomRange( this._highlightRange ) ;
     214                        this._cursors = charRange._cursors ;
     215                        this._highlightRange = null ;
    175216                }
     217        },
     218
     219        GetHighlightDomRange : function()
     220        {
     221                return this._highlightRange;
     222        },
     223
     224        MoveNext : function()
     225        {
     226                var next = this._cursors[ this._cursors.length - 1 ].Clone() ;
     227                var retval = next.MoveNext() ;
     228                if ( retval )
     229                        this._cursors = [] ;
     230                this._cursors.push( next ) ;
     231                if ( this._cursors.length > this._maxLength )
     232                        this._cursors.shift() ;
     233                return retval ;
     234        },
     235
     236        MoveBack : function()
     237        {
     238                var prev = this._cursors[0].Clone() ;
     239                var retval = prev.MoveBack() ;
     240                if ( retval )
     241                        this._cursors = [] ;
     242                this._cursors.unshift( prev ) ;
     243                if ( this._cursors.length > this._maxLength )
     244                        this._cursors.pop() ;
     245                return retval ;
     246        },
     247
     248        GetEndCharacter : function()
     249        {
     250                if ( this._cursors.length < 1 )
     251                        return null ;
     252                var retval = this._cursors[ this._cursors.length - 1 ].GetCharacter() ;
     253                return retval ;
     254        },
     255
     256        GetNextRange : function( len )
     257        {               
     258                if ( this._cursors.length == 0 )
     259                        return null ;
     260                var cur = this._cursors[ this._cursors.length - 1 ].Clone() ;
     261                cur.MoveNext() ;
     262                return new CharacterRange( cur, len ) ;
    176263        }
    177         return cursor ;
    178 }
     264} ;
    179265
    180 // With this function, we can treat the bookmark as an iterator for DFS.
    181 function NextPosition( bookmark )
     266CharacterRange.CreateFromDomRange = function( domRange )
    182267{
    183         // See if there's anything further down the tree.
    184         var next = bookmark.concat( [0] ) ;
    185         if ( GetData( next ) != null )
    186                 return next ;
     268        var w3cRange = domRange._Range ;
     269        var startContainer = w3cRange.startContainer ;
     270        var endContainer = w3cRange.endContainer ;
     271        var startTextNode, startIndex, endTextNode, endIndex ;
    187272
    188         // Nothing down there? See if there's anything next to me.
    189         var next = bookmark.slice( 0, bookmark.length - 1 ).concat( [ bookmark[ bookmark.length - 1 ] + 1 ] ) ;
    190         if ( GetData( next ) != null )
    191                 return next ;
     273        if ( startContainer.nodeType == 3 )
     274        {
     275                startTextNode = startContainer ;
     276                startIndex = w3cRange.startOffset ;
     277        }
     278        else if ( domRange.StartNode.nodeType == 3 )
     279        {
     280                startTextNode = domRange.StartNode ;
     281                startIndex = 0 ;
     282        }
     283        else
     284        {
     285                startTextNode = GetNextNonEmptyTextNode( domRange.StartNode, domRange.StartNode.parentNode ) ;
     286                if ( !startTextNode )
     287                        return null ;
     288                startIndex = 0 ;
     289        }
    192290
    193         // Nothing even next to me? See if there's anything next to my ancestors.
    194         for ( var i = bookmark.length - 1 ; i > 0 ; i-- )
     291        if ( endContainer.nodeType == 3 && w3cRange.endOffset > 0 )
    195292        {
    196                 var next = bookmark.slice( 0, i - 1 ).concat( [ bookmark[ i - 1 ] + 1 ] ) ;
    197                 if ( GetData( next ) != null )
    198                         return next ;
     293                endTextNode = endContainer ;
     294                endIndex = w3cRange.endOffset - 1 ;
    199295        }
     296        else
     297        {
     298                endTextNode = domRange.EndNode ;
     299                while ( endTextNode.nodeType != 3 )
     300                        endTextNode = endTextNode.lastChild ;
     301                endIndex = endTextNode.length - 1 ;
     302        }
    200303
    201         // There's absolutely nothing left to walk, return null.
    202         return null ;
    203 }
    204 
    205 // Is this character a unicode whitespace?
    206 // Reference: http://unicode.org/Public/UNIDATA/PropList.txt
    207 function CheckIsWhitespace( c )
    208 {
    209         var code = c.charCodeAt( 0 );
    210         if ( code >= 9 && code <= 0xd )
    211                 return true;
    212         if ( code >= 0x2000 && code <= 0x200a )
    213                 return true;
    214         switch ( code )
     304        var cursors = [] ;
     305        var current = new CharacterCursor( startTextNode, startIndex ) ;
     306        cursors.push( current ) ;
     307        do
    215308        {
    216                 case 0x20:
    217                 case 0x85:
    218                 case 0xa0:
    219                 case 0x1680:
    220                 case 0x180e:
    221                 case 0x2028:
    222                 case 0x2029:
    223                 case 0x202f:
    224                 case 0x205f:
    225                 case 0x3000:
    226                         return true;
    227                 default:
    228                         return false;
     309                current = current.Clone() ;
     310                current.MoveNext() ;
     311                cursors.push( current ) ;
    229312        }
     313        while ( !( current.GetTextNode() == endTextNode && current.GetIndex() == endIndex ) ) ;
     314
     315        return new CharacterRange( cursors, cursors.length ) ;
    230316}
    231317
    232318// Knuth-Morris-Pratt Algorithm for stream input
    233319KMP_NOMATCH = 0 ;
    234320KMP_ADVANCED = 1 ;
    235321KMP_MATCHED = 2 ;
    236 function KmpMatch( pattern, ignoreCase )
     322KmpMatch = function( pattern, ignoreCase )
    237323{
    238324        var overlap = [ -1 ] ;
    239325        for ( var i = 0 ; i < pattern.length ; i++ )
     
    251337                this.Pattern = pattern ;
    252338}
    253339KmpMatch.prototype = {
    254         "FeedCharacter" : function( c )
     340        FeedCharacter : function( c )
    255341        {
    256342                if ( this._IgnoreCase )
    257343                        c = c.toLowerCase();
     
    277363
    278364                return null ;
    279365        },
    280         "Reset" : function()
     366
     367        Reset : function()
    281368        {
    282369                this._State = 0 ;
    283370        }
    284371};
    285372
    286 function _Find()
     373// Place a range at the start of document.
     374function OnLoad()
    287375{
    288         // Start from the end of the current selection.
    289         var matcher = new KmpMatch( GetSearchString(), ! GetCheckCase() ) ;
    290         var cursor = GlobalRange.CreateBookmark2().End ;
    291         var matchState = KMP_NOMATCH ;
    292         var matchBookmark = null ;
    293         var matchBookmarkStart = [] ;
     376        // First of all, translate the dialog box texts.
     377        oEditor.FCKLanguageManager.TranslatePage( document ) ;
    294378
    295         // Match finding.
    296         while ( true )
     379        // Show the appropriate tab at startup.
     380        if ( dialogArguments.CustomValue == 'Find' )
    297381        {
    298                 // Perform KMP stream matching.
    299                 //      - Reset KMP matcher if we encountered a block element.
    300                 var data = GetData( cursor ) ;
    301                 if ( data )
    302                 {
    303                         if ( data.tagName )
    304                         {
    305                                 if ( oEditor.FCKListsLib.BlockElements[ data.tagName.toLowerCase() ] )
    306                                 {
    307                                         matcher.Reset();
    308                                         matchBookmarkStart = [] ;
    309                                 }
    310                         }
    311                         else if ( data.charAt != undefined )
    312                         {
    313                                 matchState = matcher.FeedCharacter(data) ;
     382                dialog.SetSelectedTab( 'Find' ) ;
     383                dialog.SetAutoSize( true ) ;
     384        }
     385        else
     386                dialog.SetSelectedTab( 'Replace' ) ;
    314387
    315                                 // No possible match of any useful substring in the pattern for the currently scanned character.
    316                                 // So delete any positional information.
    317                                 if ( matchState == KMP_NOMATCH )
    318                                         matchBookmarkStart = [] ;
    319                                 // We've matched something, but it's not a complete match, so let's just mark down the position for backtracking later.
    320                                 else if ( matchState == KMP_ADVANCED )
    321                                 {
    322                                         matchBookmarkStart.push( cursor.concat( [] ) ) ;
    323                                         if ( matchBookmarkStart.length > matcher._State )
    324                                                 matchBookmarkStart.shift() ;
    325                                 }
    326                                 // Found a complete match! Mark down the ending position as well.
    327                                 else if ( matchState == KMP_MATCHED )
    328                                 {
    329                                         // It is possible to get a KMP_MATCHED without KMP_ADVANCED when the match pattern is only 1 character.
    330                                         // So need to check and mark down the starting position as well.
    331                                         if ( matchBookmarkStart.length == 0 )
    332                                                 matchBookmarkStart = [cursor.concat( [] )] ;
     388        SelectField( 'txtFind' + dialogArguments.CustomValue ) ;
     389}
    333390
    334                                         matchBookmark = { 'Start' : matchBookmarkStart.shift(), 'End' : cursor.concat( [] ) } ;
    335                                         matchBookmark.End[ matchBookmark.End.length - 1 ]++;
     391function btnStat()
     392{
     393        GetE('btnReplace').disabled =
     394                GetE('btnReplaceAll').disabled =
     395                        GetE('btnFind').disabled =
     396                                ( GetE(idMap["FindText"]).value.length == 0 ) ;
     397}
    336398
    337                                         // Wait, do we have to match a whole word?
    338                                         // If yes, carry out additional checks on what we've got.
    339                                         if ( GetMatchWord() )
    340                                         {
    341                                                 var startOk = false ;
    342                                                 var endOk = false ;
    343                                                 var start = matchBookmark.Start ;
    344                                                 var end = matchBookmark.End ;
    345                                                 if ( start[ start.length - 1 ] == 0 )
    346                                                         startOk = true ;
    347                                                 else
    348                                                 {
    349                                                         var cursorBeforeStart = start.slice( 0, start.length - 1 ) ;
    350                                                         cursorBeforeStart.push( start[ start.length - 1 ] - 1 ) ;
    351                                                         var dataBeforeStart = GetData( cursorBeforeStart ) ;
    352                                                         if ( dataBeforeStart == null || dataBeforeStart.charAt == undefined )
    353                                                                 startOk = true ;
    354                                                         else if ( CheckIsWhitespace( dataBeforeStart ) )
    355                                                                 startOk = true ;
    356                                                 }
     399function btnStatDelayed()
     400{
     401        setTimeout( btnStat, 1 ) ;
     402}
    357403
    358                                                 // this is already one character beyond the last char, no need to move
    359                                                 var cursorAfterEnd = end ;
    360                                                 var dataAfterEnd = GetData( cursorAfterEnd );
    361                                                 if ( dataAfterEnd == null || dataAfterEnd.charAt == undefined )
    362                                                         endOk = true ;
    363                                                 else if ( CheckIsWhitespace( dataAfterEnd ) )
    364                                                         endOk = true ;
     404function GetSearchString()
     405{
     406        return GetE(idMap['FindText']).value ;
     407}
    365408
    366                                                 if ( startOk && endOk )
    367                                                         break ;
    368                                                 else
    369                                                         matcher.Reset() ;
    370                                         }
    371                                         else
    372                                                 break ;
    373                                 }
    374                         }
    375                 }
     409function GetReplaceString()
     410{
     411        return GetE("txtReplace").value ;
     412}
    376413
    377                 // Perform DFS across the document, until we've reached the end.
    378                 cursor = NextPosition( cursor ) ;
    379                 if ( cursor == null )
    380                         break;
     414function GetCheckCase()
     415{
     416        return !! ( GetE(idMap['CheckCase']).checked ) ;
     417}
     418
     419function GetMatchWord()
     420{
     421        return !! ( GetE(idMap['CheckWord']).checked ) ;
     422}
     423
     424// Is this character a unicode whitespace?
     425// Reference: http://unicode.org/Public/UNIDATA/PropList.txt
     426function CheckIsWhitespace( c )
     427{
     428        var code = c.charCodeAt( 0 );
     429        if ( code >= 9 && code <= 0xd )
     430                return true;
     431        if ( code >= 0x2000 && code <= 0x200a )
     432                return true;
     433        switch ( code )
     434        {
     435                case 0x20:
     436                case 0x85:
     437                case 0xa0:
     438                case 0x1680:
     439                case 0x180e:
     440                case 0x2028:
     441                case 0x2029:
     442                case 0x202f:
     443                case 0x205f:
     444                case 0x3000:
     445                        return true;
     446                default:
     447                        return false;
    381448        }
     449}
    382450
    383         // If we've found a match, highlight the match.
     451FindRange = null ;
     452function _Find()
     453{
     454        var searchString = GetSearchString() ;
     455        if ( !FindRange )
     456                FindRange = new CharacterRange( new CharacterCursor( EditorDocument ), searchString.length ) ;
     457        else
     458        {
     459                FindRange.RemoveHighlight() ;
     460                FindRange = FindRange.GetNextRange( searchString.length ) ;
     461        }
     462        var matcher = new KmpMatch( searchString, ! GetCheckCase() ) ;
     463        var matchState = KMP_NOMATCH ;
     464        var character = null ;
     465
     466        while ( ( character = FindRange.GetEndCharacter() ) )
     467        {
     468                matchState = matcher.FeedCharacter( character ) ;
     469                if ( matchState == KMP_MATCHED )
     470                        break ;
     471                if ( FindRange.MoveNext() )
     472                        matcher.Reset() ;
     473        }
     474
    384475        if ( matchState == KMP_MATCHED )
    385476        {
    386                 GlobalRange.MoveToBookmark2( matchBookmark ) ;
    387                 Highlight() ;
    388                 var focus = GlobalRange._Range.endContainer ;
    389                 while ( focus && focus.nodeType != 1 )
    390                         focus = focus.parentNode ;
    391 
    392                 if ( focus )
     477                if ( GetMatchWord() )
    393478                {
    394                         if ( oEditor.FCKBrowserInfo.IsSafari )
    395                                 oEditor.FCKDomTools.ScrollIntoView( focus, false ) ;
    396                         else
    397                                 focus.scrollIntoView( false ) ;
    398479                }
    399480
     481                FindRange.Highlight() ;
    400482                return true ;
    401483        }
    402484        else
    403485        {
    404                 ResetGlobalRange() ;
     486                FindRange = null ;
    405487                return false ;
    406488        }
    407489}
     
    409491function Find()
    410492{
    411493        if ( ! _Find() )
    412         {
    413                 ClearHighlight() ;
    414494                alert( FCKLang.DlgFindNotFoundMsg ) ;
    415         }
    416495}
    417496
    418497function Replace()
    419498{
    420         if ( GlobalRange.CheckIsCollapsed() )
     499        if ( FindRange && FindRange.GetHighlightDomRange() )
    421500        {
    422                 if (! _Find() )
     501                var range = FindRange.GetHighlightDomRange() ;
     502                var bookmark = range.CreateBookmark() ;
     503                FindRange.RemoveHighlight() ;
     504                range.MoveToBookmark( bookmark ) ;
     505
     506                oEditor.FCKUndo.SaveUndoStep() ;
     507                range.DeleteContents() ;
     508                range.InsertNode( EditorDocument.createTextNode( GetReplaceString() ) ) ;
     509                range._UpdateElementInfo() ;
     510
     511                FindRange = CharacterRange.CreateFromDomRange( range ) ;
     512        }
     513        else
     514        {
     515                if ( ! _Find() )
    423516                {
    424                         ClearHighlight() ;
     517                        FindRange && FindRange.RemoveHighlight() ;
    425518                        alert( FCKLang.DlgFindNotFoundMsg ) ;
    426519                }
    427520        }
    428         else
    429         {
    430                 oEditor.FCKUndo.SaveUndoStep() ;
    431                 GlobalRange.DeleteContents() ;
    432                 GlobalRange.InsertNode( oEditor.FCK.EditorDocument.createTextNode( GetReplaceString() ) ) ;
    433                 GlobalRange.Collapse( false ) ;
    434         }
    435521}
    436522
    437523function ReplaceAll()
     
    441527
    442528        while ( _Find() )
    443529        {
    444                 dialog.Selection.EnsureSelection() ;
    445                 GlobalRange.DeleteContents() ;
    446                 GlobalRange.InsertNode( oEditor.FCK.EditorDocument.createTextNode( GetReplaceString() ) ) ;
    447                 GlobalRange.Collapse( false ) ;
     530                var range = FindRange.GetHighlightDomRange() ;
     531                var bookmark = range.CreateBookmark() ;
     532                FindRange.RemoveHighlight() ;
     533                range.MoveToBookmark( bookmark) ;
     534
     535                range.DeleteContents() ;
     536                range.InsertNode( EditorDocument.createTextNode( GetReplaceString() ) ) ;
     537                range._UpdateElementInfo() ;
     538
     539                FindRange = CharacterRange.CreateFromDomRange( range ) ;
    448540                replaceCount++ ;
    449541        }
    450542        if ( replaceCount == 0 )
    451543        {
    452                 ClearHighlight() ;
     544                FindRange && FindRange.RemoveHighlight() ;
    453545                alert( FCKLang.DlgFindNotFoundMsg ) ;
    454546        }
    455547        dialog.Cancel() ;
    456548}
    457549
    458 window.onunload = function(){ ClearHighlight() ; }
     550window.onunload = function(){ if ( FindRange ) FindRange.RemoveHighlight() ; }
    459551        </script>
    460552</head>
    461553<body onload="OnLoad()" style="overflow: hidden">
© 2003 – 2019 CKSource – Frederico Knabben. All rights reserved. | Terms of use | Privacy policy