Ticket #2150: 2150_pre.patch
File 2150_pre.patch, 20.7 KB (added by , 16 years ago) |
---|
-
editor/dialog/fck_replace.html
34 34 var dialogArguments = dialog.Args() ; 35 35 36 36 var FCKLang = oEditor.FCKLang ; 37 var FCKDomTools = oEditor.FCKDomTools ; 38 var FCKDomRange = oEditor.FCKDomRange ; 39 var FCKListsLib = oEditor.FCKListsLib ; 40 var FCKTools = oEditor.FCKTools ; 41 var EditorDocument = oEditor.FCK.EditorDocument ; 42 var HighlightStyle = oEditor.FCKStyles.GetStyle( '_FCK_SelectionHighlight' ) ; 37 43 38 44 dialog.AddTab( 'Find', FCKLang.DlgFindTitle ) ; 39 45 dialog.AddTab( 'Replace', FCKLang.DlgReplaceTitle ) ; … … 51 57 dialog.SetAutoSize( true ) ; 52 58 } 53 59 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() 60 GetNextNonEmptyTextNode = function( node, stopNode ) 59 61 { 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 ; 63 65 } 64 ResetGlobalRange() ;65 66 66 var HighlightRange = null ; 67 function Highlight() 67 CharacterCursor = function( arg ) 68 68 { 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 ) 80 70 { 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 ; 83 74 } 75 else 76 { 77 this._textNode = arguments[0] ; 78 this._offset = arguments[1] ; 79 this._doc = FCKTools.GetElementDocument( arguments[0] ) ; 80 } 84 81 } 85 86 function OnLoad() 82 CharacterCursor.prototype = 87 83 { 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 }, 90 88 91 // Show the appropriate tab at startup.92 if ( dialogArguments.CustomValue == 'Find')89 // Non-normalized. 90 GetTextNode : function() 93 91 { 94 dialog.SetSelectedTab( 'Find' ) ; 95 dialog.SetAutoSize( true ) ; 96 } 97 else 98 dialog.SetSelectedTab( 'Replace' ) ; 92 return this._textNode ; 93 }, 99 94 100 SelectField( 'txtFind' + dialogArguments.CustomValue ) ; 101 } 95 // Non-normalized. 96 GetIndex : function() 97 { 98 return this._offset ; 99 }, 102 100 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 }, 110 113 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 } 115 122 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 } 120 132 121 function GetReplaceString() 122 { 123 return GetE("txtReplace").value;124 } 133 this._textNode = curNode ; 134 this._offset = 0 ; 135 return crossed ; 136 }, 125 137 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 } 130 146 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 168 CharacterRange = function( initCursor, maxLength ) 132 169 { 133 return !! ( GetE(idMap['CheckWord']).checked ) ; 170 this._cursors = initCursor.push ? initCursor : [initCursor] ; 171 this._maxLength = maxLength ; 172 this._highlightRange = null ; 134 173 } 135 136 // Get the data pointed to by a bookmark. 137 function GetData( bookmark ) 174 CharacterRange.prototype = 138 175 { 139 var cursor = oEditor.FCK.EditorDocument.documentElement ; 140 for ( var i = 0 ; i < bookmark.length ; i++ ) 176 ToDomRange : function() 141 177 { 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 ) ; 163 203 else 204 focusNode.scrollIntoView( false ) ; 205 this._cursors = charRange._cursors ; 206 }, 207 208 RemoveHighlight : function() 209 { 210 if ( this._highlightRange ) 164 211 { 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 ; 175 216 } 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 ) ; 176 263 } 177 return cursor ; 178 } 264 } ; 179 265 180 // With this function, we can treat the bookmark as an iterator for DFS. 181 function NextPosition( bookmark ) 266 CharacterRange.CreateFromDomRange = function( domRange ) 182 267 { 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 ; 187 272 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 } 192 290 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 ) 195 292 { 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 ; 199 295 } 296 else 297 { 298 endTextNode = domRange.EndNode ; 299 while ( endTextNode.nodeType != 3 ) 300 endTextNode = endTextNode.lastChild ; 301 endIndex = endTextNode.length - 1 ; 302 } 200 303 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 215 308 { 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 ) ; 229 312 } 313 while ( !( current.GetTextNode() == endTextNode && current.GetIndex() == endIndex ) ) ; 314 315 return new CharacterRange( cursors, cursors.length ) ; 230 316 } 231 317 232 318 // Knuth-Morris-Pratt Algorithm for stream input 233 319 KMP_NOMATCH = 0 ; 234 320 KMP_ADVANCED = 1 ; 235 321 KMP_MATCHED = 2 ; 236 function KmpMatch( pattern, ignoreCase )322 KmpMatch = function( pattern, ignoreCase ) 237 323 { 238 324 var overlap = [ -1 ] ; 239 325 for ( var i = 0 ; i < pattern.length ; i++ ) … … 251 337 this.Pattern = pattern ; 252 338 } 253 339 KmpMatch.prototype = { 254 "FeedCharacter": function( c )340 FeedCharacter : function( c ) 255 341 { 256 342 if ( this._IgnoreCase ) 257 343 c = c.toLowerCase(); … … 277 363 278 364 return null ; 279 365 }, 280 "Reset" : function() 366 367 Reset : function() 281 368 { 282 369 this._State = 0 ; 283 370 } 284 371 }; 285 372 286 function _Find() 373 // Place a range at the start of document. 374 function OnLoad() 287 375 { 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 ) ; 294 378 295 // Match finding.296 while ( true)379 // Show the appropriate tab at startup. 380 if ( dialogArguments.CustomValue == 'Find' ) 297 381 { 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' ) ; 314 387 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 } 333 390 334 matchBookmark = { 'Start' : matchBookmarkStart.shift(), 'End' : cursor.concat( [] ) } ; 335 matchBookmark.End[ matchBookmark.End.length - 1 ]++; 391 function btnStat() 392 { 393 GetE('btnReplace').disabled = 394 GetE('btnReplaceAll').disabled = 395 GetE('btnFind').disabled = 396 ( GetE(idMap["FindText"]).value.length == 0 ) ; 397 } 336 398 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 } 399 function btnStatDelayed() 400 { 401 setTimeout( btnStat, 1 ) ; 402 } 357 403 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 ; 404 function GetSearchString() 405 { 406 return GetE(idMap['FindText']).value ; 407 } 365 408 366 if ( startOk && endOk ) 367 break ; 368 else 369 matcher.Reset() ; 370 } 371 else 372 break ; 373 } 374 } 375 } 409 function GetReplaceString() 410 { 411 return GetE("txtReplace").value ; 412 } 376 413 377 // Perform DFS across the document, until we've reached the end. 378 cursor = NextPosition( cursor ) ; 379 if ( cursor == null ) 380 break; 414 function GetCheckCase() 415 { 416 return !! ( GetE(idMap['CheckCase']).checked ) ; 417 } 418 419 function 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 426 function 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; 381 448 } 449 } 382 450 383 // If we've found a match, highlight the match. 451 FindRange = null ; 452 function _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 384 475 if ( matchState == KMP_MATCHED ) 385 476 { 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() ) 393 478 { 394 if ( oEditor.FCKBrowserInfo.IsSafari )395 oEditor.FCKDomTools.ScrollIntoView( focus, false ) ;396 else397 focus.scrollIntoView( false ) ;398 479 } 399 480 481 FindRange.Highlight() ; 400 482 return true ; 401 483 } 402 484 else 403 485 { 404 ResetGlobalRange();486 FindRange = null ; 405 487 return false ; 406 488 } 407 489 } … … 409 491 function Find() 410 492 { 411 493 if ( ! _Find() ) 412 {413 ClearHighlight() ;414 494 alert( FCKLang.DlgFindNotFoundMsg ) ; 415 }416 495 } 417 496 418 497 function Replace() 419 498 { 420 if ( GlobalRange.CheckIsCollapsed() )499 if ( FindRange && FindRange.GetHighlightDomRange() ) 421 500 { 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() ) 423 516 { 424 ClearHighlight() ;517 FindRange && FindRange.RemoveHighlight() ; 425 518 alert( FCKLang.DlgFindNotFoundMsg ) ; 426 519 } 427 520 } 428 else429 {430 oEditor.FCKUndo.SaveUndoStep() ;431 GlobalRange.DeleteContents() ;432 GlobalRange.InsertNode( oEditor.FCK.EditorDocument.createTextNode( GetReplaceString() ) ) ;433 GlobalRange.Collapse( false ) ;434 }435 521 } 436 522 437 523 function ReplaceAll() … … 441 527 442 528 while ( _Find() ) 443 529 { 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 ) ; 448 540 replaceCount++ ; 449 541 } 450 542 if ( replaceCount == 0 ) 451 543 { 452 ClearHighlight() ;544 FindRange && FindRange.RemoveHighlight() ; 453 545 alert( FCKLang.DlgFindNotFoundMsg ) ; 454 546 } 455 547 dialog.Cancel() ; 456 548 } 457 549 458 window.onunload = function(){ ClearHighlight() ; }550 window.onunload = function(){ if ( FindRange ) FindRange.RemoveHighlight() ; } 459 551 </script> 460 552 </head> 461 553 <body onload="OnLoad()" style="overflow: hidden">