X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=_source%2Fplugins%2Ffind%2Fdialogs%2Ffind.js;h=6711fe58740d6907dc6c99dd1abea9df4ee4ea5c;hb=refs%2Ftags%2Fv3.6.1;hp=b4196fa5e98ec4e21f80a367bb08d43e36b60f1c;hpb=8761695d9b70afe75905deaac88f78c1f8aeb32d;p=ckeditor.git diff --git a/_source/plugins/find/dialogs/find.js b/_source/plugins/find/dialogs/find.js index b4196fa..6711fe5 100644 --- a/_source/plugins/find/dialogs/find.js +++ b/_source/plugins/find/dialogs/find.js @@ -1,23 +1,24 @@ /* -Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved. +Copyright (c) 2003-2011, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.html or http://ckeditor.com/license */ (function() { - function guardDomWalkerNonEmptyTextNode( node ) + var isReplace; + + function findEvaluator( node ) { - return ( node.type == CKEDITOR.NODE_TEXT && node.getLength() > 0 ); + return node.type == CKEDITOR.NODE_TEXT && node.getLength() > 0 && ( !isReplace || !node.isReadOnly() ); } /** * Elements which break characters been considered as sequence. */ - function checkCharactersBoundary ( node ) + function nonCharactersBoundary( node ) { - var dtd = CKEDITOR.dtd; - return node.isBlockBoundary( - CKEDITOR.tools.extend( {}, dtd.$empty, dtd.$nonEditable ) ); + return !( node.type == CKEDITOR.NODE_ELEMENT && node.isBlockBoundary( + CKEDITOR.tools.extend( {}, CKEDITOR.dtd.$empty, CKEDITOR.dtd.$nonEditable ) ) ); } /** @@ -67,8 +68,11 @@ For licensing, see LICENSE.html or http://ckeditor.com/license var findDialog = function( editor, startupPage ) { - // Style object for highlights. - var highlightStyle = new CKEDITOR.style( editor.config.find_highlight ); + // Style object for highlights: (#5018) + // 1. Defined as full match style to avoid compromising ordinary text color styles. + // 2. Must be apply onto inner-most text to avoid conflicting with ordinary text color styles visually. + var highlightStyle = new CKEDITOR.style( CKEDITOR.tools.extend( { fullMatch : true, childRule : function(){ return 0; } }, + editor.config.find_highlight ) ); /** * Iterator which walk through the specified range char by char. By @@ -79,11 +83,21 @@ For licensing, see LICENSE.html or http://ckeditor.com/license */ var characterWalker = function( range , matchWord ) { + var self = this; var walker = new CKEDITOR.dom.walker( range ); - walker[ matchWord ? 'guard' : 'evaluator' ] = - guardDomWalkerNonEmptyTextNode; - walker.breakOnFalse = true; + walker.guard = matchWord ? nonCharactersBoundary : function( node ) + { + !nonCharactersBoundary( node ) && ( self._.matchBoundary = true ); + }; + walker[ 'evaluator' ] = findEvaluator; + walker.breakOnFalse = 1; + + if ( range.startContainer.type == CKEDITOR.NODE_TEXT ) + { + this.textNode = range.startContainer; + this.offset = range.startOffset - 1; + } this._ = { matchWord : matchWord, @@ -107,20 +121,20 @@ For licensing, see LICENSE.html or http://ckeditor.com/license { var currentTextNode = this.textNode; // Already at the end of document, no more character available. - if( currentTextNode === null ) + if ( currentTextNode === null ) return cursorStep.call( this ); this._.matchBoundary = false; // There are more characters in the text node, step forward. - if( currentTextNode + if ( currentTextNode && rtl && this.offset > 0 ) { this.offset--; return cursorStep.call( this ); } - else if( currentTextNode + else if ( currentTextNode && this.offset < currentTextNode.getLength() - 1 ) { this.offset++; @@ -138,14 +152,8 @@ For licensing, see LICENSE.html or http://ckeditor.com/license // Stop searching if we're need full word match OR // already reach document end. if ( this._.matchWord && !currentTextNode - ||this._.walker._.end ) + || this._.walker._.end ) break; - - // Marking as match character boundaries. - if( !currentTextNode - && checkCharactersBoundary( this._.walker.current ) ) - this._.matchBoundary = true; - } // Found a fresh text node. this.textNode = currentTextNode; @@ -171,7 +179,7 @@ For licensing, see LICENSE.html or http://ckeditor.com/license cursors : [], rangeLength : rangeLength, highlightRange : null, - isMatched : false + isMatched : 0 }; }; @@ -181,16 +189,25 @@ For licensing, see LICENSE.html or http://ckeditor.com/license */ toDomRange : function() { + var range = new CKEDITOR.dom.range( editor.document ); var cursors = this._.cursors; if ( cursors.length < 1 ) - return null; + { + var textNode = this._.walker.textNode; + if ( textNode ) + range.setStartAfter( textNode ); + else + return null; + } + else + { + var first = cursors[0], + last = cursors[ cursors.length - 1 ]; - var first = cursors[0], - last = cursors[ cursors.length - 1 ], - range = new CKEDITOR.dom.range( editor.document ); + range.setStart( first.textNode, first.offset ); + range.setEnd( last.textNode, last.offset + 1 ); + } - range.setStart( first.textNode, first.offset ); - range.setEnd( last.textNode, last.offset + 1 ); return range; }, /** @@ -240,8 +257,10 @@ For licensing, see LICENSE.html or http://ckeditor.com/license this.removeHighlight(); // Apply the highlight. - var range = this.toDomRange(); + var range = this.toDomRange(), + bookmark = range.createBookmark(); highlightStyle.applyToRange( range ); + range.moveToBookmark( bookmark ); this._.highlightRange = range; // Scroll the editor to the highlighted area. @@ -262,11 +281,21 @@ For licensing, see LICENSE.html or http://ckeditor.com/license if ( !this._.highlightRange ) return; + var bookmark = this._.highlightRange.createBookmark(); highlightStyle.removeFromRange( this._.highlightRange ); + this._.highlightRange.moveToBookmark( bookmark ); this.updateFromDomRange( this._.highlightRange ); this._.highlightRange = null; }, + isReadOnly : function() + { + if ( !this._.highlightRange ) + return 0; + + return this._.highlightRange.startContainer.isReadOnly(); + }, + moveBack : function() { var retval = this._.walker.back(), @@ -310,13 +339,16 @@ For licensing, see LICENSE.html or http://ckeditor.com/license getNextCharacterRange : function( maxLength ) { var lastCursor, + nextRangeWalker, cursors = this._.cursors; - if ( !( lastCursor = cursors[ cursors.length - 1 ] ) ) - return null; - return new characterRange( - new characterWalker( - getRangeAfterCursor( lastCursor ) ), - maxLength ); + + if ( ( lastCursor = cursors[ cursors.length - 1 ] ) && lastCursor.textNode ) + nextRangeWalker = new characterWalker( getRangeAfterCursor( lastCursor ) ); + // In case it's an empty range (no cursors), figure out next range from walker (#4951). + else + nextRangeWalker = this._.walker; + + return new characterRange( nextRangeWalker, maxLength ); }, getCursors : function() @@ -427,7 +459,7 @@ For licensing, see LICENSE.html or http://ckeditor.com/license matchRange : null, find : function( pattern, matchCase, matchWord, matchCyclic, highlightMatched, cyclicRerun ) { - if( !this.matchRange ) + if ( !this.matchRange ) this.matchRange = new characterRange( new characterWalker( this.searchRange ), @@ -483,7 +515,7 @@ For licensing, see LICENSE.html or http://ckeditor.com/license // Re-run the finding once for cyclic.(#3517) if ( matchCyclic && !cyclicRerun ) { - this.searchRange = getSearchRange( true ); + this.searchRange = getSearchRange( 1 ); this.matchRange = null; return arguments.callee.apply( this, Array.prototype.slice.call( arguments ).concat( [ true ] ) ); @@ -500,13 +532,15 @@ For licensing, see LICENSE.html or http://ckeditor.com/license replace : function( dialog, pattern, newString, matchCase, matchWord, matchCyclic , isReplaceAll ) { + isReplace = 1; + // Successiveness of current replace/find. - var result = false; + var result = 0; // 1. Perform the replace when there's already a match here. // 2. Otherwise perform the find but don't replace it immediately. if ( this.matchRange && this.matchRange.isMatched() - && !this.matchRange._.isReplaced ) + && !this.matchRange._.isReplaced && !this.matchRange.isReadOnly() ) { // Turn off highlight for a while when saving snapshots. this.matchRange.removeHighlight(); @@ -531,11 +565,13 @@ For licensing, see LICENSE.html or http://ckeditor.com/license this.matchRange.highlight(); this.matchRange._.isReplaced = true; this.replaceCounter++; - result = true; + result = 1; } else result = this.find( pattern, matchCase, matchWord, matchCyclic, !isReplaceAll ); + isReplace = 0; + return result; } }; @@ -563,17 +599,18 @@ For licensing, see LICENSE.html or http://ckeditor.com/license return searchRange; } + var lang = editor.lang.findAndReplace; return { - title : editor.lang.findAndReplace.title, + title : lang.title, resizable : CKEDITOR.DIALOG_RESIZE_NONE, minWidth : 350, - minHeight : 165, - buttons : [ CKEDITOR.dialog.cancelButton ], //Cancel button only. + minHeight : 170, + buttons : [ CKEDITOR.dialog.cancelButton ], // Cancel button only. contents : [ { id : 'find', - label : editor.lang.findAndReplace.find, - title : editor.lang.findAndReplace.find, + label : lang.find, + title : lang.find, accessKey : '', elements : [ { @@ -584,16 +621,17 @@ For licensing, see LICENSE.html or http://ckeditor.com/license { type : 'text', id : 'txtFindFind', - label : editor.lang.findAndReplace.findWhat, + label : lang.findWhat, isChanged : false, labelLayout : 'horizontal', accessKey : 'F' }, { type : 'button', + id : 'btnFind', align : 'left', style : 'width:100%', - label : editor.lang.findAndReplace.find, + label : lang.find, onClick : function() { var dialog = this.getDialog(); @@ -601,7 +639,7 @@ For licensing, see LICENSE.html or http://ckeditor.com/license dialog.getValueOf( 'find', 'txtFindCaseChk' ), dialog.getValueOf( 'find', 'txtFindWordChk' ), dialog.getValueOf( 'find', 'txtFindCyclic' ) ) ) - alert( editor.lang.findAndReplace + alert( lang .notFoundMsg ); } } @@ -617,20 +655,20 @@ For licensing, see LICENSE.html or http://ckeditor.com/license id : 'txtFindCaseChk', isChanged : false, style : 'margin-top:28px', - label : editor.lang.findAndReplace.matchCase + label : lang.matchCase }, { type : 'checkbox', id : 'txtFindWordChk', isChanged : false, - label : editor.lang.findAndReplace.matchWord + label : lang.matchWord }, { type : 'checkbox', id : 'txtFindCyclic', isChanged : false, 'default' : true, - label : editor.lang.findAndReplace.matchCyclic + label : lang.matchCyclic } ] } @@ -638,7 +676,7 @@ For licensing, see LICENSE.html or http://ckeditor.com/license }, { id : 'replace', - label : editor.lang.findAndReplace.replace, + label : lang.replace, accessKey : 'M', elements : [ { @@ -649,16 +687,17 @@ For licensing, see LICENSE.html or http://ckeditor.com/license { type : 'text', id : 'txtFindReplace', - label : editor.lang.findAndReplace.findWhat, + label : lang.findWhat, isChanged : false, labelLayout : 'horizontal', accessKey : 'F' }, { type : 'button', + id : 'btnFindReplace', align : 'left', style : 'width:100%', - label : editor.lang.findAndReplace.replace, + label : lang.replace, onClick : function() { var dialog = this.getDialog(); @@ -668,7 +707,7 @@ For licensing, see LICENSE.html or http://ckeditor.com/license dialog.getValueOf( 'replace', 'txtReplaceCaseChk' ), dialog.getValueOf( 'replace', 'txtReplaceWordChk' ), dialog.getValueOf( 'replace', 'txtReplaceCyclic' ) ) ) - alert( editor.lang.findAndReplace + alert( lang .notFoundMsg ); } } @@ -682,16 +721,17 @@ For licensing, see LICENSE.html or http://ckeditor.com/license { type : 'text', id : 'txtReplace', - label : editor.lang.findAndReplace.replaceWith, + label : lang.replaceWith, isChanged : false, labelLayout : 'horizontal', accessKey : 'R' }, { type : 'button', + id : 'btnReplaceAll', align : 'left', style : 'width:100%', - label : editor.lang.findAndReplace.replaceAll, + label : lang.replaceAll, isChanged : false, onClick : function() { @@ -701,14 +741,14 @@ For licensing, see LICENSE.html or http://ckeditor.com/license finder.replaceCounter = 0; // Scope to full document. - finder.searchRange = getSearchRange( true ); + finder.searchRange = getSearchRange( 1 ); if ( finder.matchRange ) { finder.matchRange.removeHighlight(); finder.matchRange = null; } editor.fire( 'saveSnapshot' ); - while( finder.replace( dialog, + while ( finder.replace( dialog, dialog.getValueOf( 'replace', 'txtFindReplace' ), dialog.getValueOf( 'replace', 'txtReplace' ), dialog.getValueOf( 'replace', 'txtReplaceCaseChk' ), @@ -718,11 +758,11 @@ For licensing, see LICENSE.html or http://ckeditor.com/license if ( finder.replaceCounter ) { - alert( editor.lang.findAndReplace.replaceSuccessMsg.replace( /%1/, finder.replaceCounter ) ); + alert( lang.replaceSuccessMsg.replace( /%1/, finder.replaceCounter ) ); editor.fire( 'saveSnapshot' ); } else - alert( editor.lang.findAndReplace.notFoundMsg ); + alert( lang.notFoundMsg ); } } ] @@ -736,14 +776,14 @@ For licensing, see LICENSE.html or http://ckeditor.com/license type : 'checkbox', id : 'txtReplaceCaseChk', isChanged : false, - label : editor.lang.findAndReplace + label : lang .matchCase }, { type : 'checkbox', id : 'txtReplaceWordChk', isChanged : false, - label : editor.lang.findAndReplace + label : lang .matchWord }, { @@ -751,7 +791,7 @@ For licensing, see LICENSE.html or http://ckeditor.com/license id : 'txtReplaceCyclic', isChanged : false, 'default' : true, - label : editor.lang.findAndReplace + label : lang .matchCyclic } ] @@ -763,19 +803,19 @@ For licensing, see LICENSE.html or http://ckeditor.com/license { var dialog = this; - //keep track of the current pattern field in use. + // Keep track of the current pattern field in use. var patternField, wholeWordChkField; - //Ignore initial page select on dialog show - var isUserSelect = false; - this.on('hide', function() + // Ignore initial page select on dialog show + var isUserSelect = 0; + this.on( 'hide', function() { - isUserSelect = false; - } ); - this.on('show', function() + isUserSelect = 0; + }); + this.on( 'show', function() { - isUserSelect = true; - } ); + isUserSelect = 1; + }); this.selectPage = CKEDITOR.tools.override( this.selectPage, function( originalFunc ) { @@ -793,7 +833,7 @@ For licensing, see LICENSE.html or http://ckeditor.com/license wholeWordChkField = dialog.getContentElement( pageId, wholeWordChkFieldId ); - // prepare for check pattern text filed 'keyup' event + // Prepare for check pattern text filed 'keyup' event if ( !currPage.initialized ) { patternFieldInput = CKEDITOR.document @@ -801,8 +841,8 @@ For licensing, see LICENSE.html or http://ckeditor.com/license currPage.initialized = true; } - if( isUserSelect ) - // synchronize fields on tab switch. + // Synchronize fields on tab switch. + if ( isUserSelect ) syncFieldsBetweenTabs.call( this, pageId ); }; } ); @@ -813,23 +853,40 @@ For licensing, see LICENSE.html or http://ckeditor.com/license // Establish initial searching start position. finder.searchRange = getSearchRange(); - if ( startupPage == 'replace' ) - this.getContentElement( 'replace', 'txtFindReplace' ).focus(); - else - this.getContentElement( 'find', 'txtFindFind' ).focus(); + // Fill in the find field with selected text. + var selectedText = this.getParentEditor().getSelection().getSelectedText(), + patternFieldId = ( startupPage == 'find' ? 'txtFindFind' : 'txtFindReplace' ); + + var field = this.getContentElement( startupPage, patternFieldId ); + field.setValue( selectedText ); + field.select(); + + this.selectPage( startupPage ); + + this[ ( startupPage == 'find' && this._.editor.readOnly? 'hide' : 'show' ) + 'Page' ]( 'replace'); }, onHide : function() { + var range; if ( finder.matchRange && finder.matchRange.isMatched() ) { finder.matchRange.removeHighlight(); editor.focus(); - editor.getSelection().selectRanges( - [ finder.matchRange.toDomRange() ] ); + + range = finder.matchRange.toDomRange(); + if ( range ) + editor.getSelection().selectRanges( [ range ] ); } // Clear current session before dialog close delete finder.matchRange; + }, + onFocus : function() + { + if ( startupPage == 'replace' ) + return this.getContentElement( 'replace', 'txtFindReplace' ); + else + return this.getContentElement( 'find', 'txtFindFind' ); } }; };