Ticket #2905: 2905_3.patch

File 2905_3.patch, 27.3 KB (added by Garry Yao, 15 years ago)
  • _source/plugins/toolbar/plugin.js

     
    213213                'Outdent', 'Indent', 'Blockquote', '-',
    214214                'JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock', '-',
    215215                'Subscript', 'Superscript', '-',
     216                'Find', 'Replace', '-',
    216217                'SelectAll', 'RemoveFormat', '-',
    217218                'Link', 'Unlink', 'Anchor', '-',
    218219                'Table', 'Smiley', 'HorizontalRule', 'SpecialChar', 'PageBreak'
  • _source/plugins/find/dialogs/find.js

     
    55
    66(function()
    77{
     8        // Element tag names which prevent characters counting.
     9        var characterBoundaryElementsEnum =
     10        {
     11                address :1, blockquote :1, dl :1, h1 :1, h2 :1, h3 :1,
     12                h4 :1, h5 :1, h6 :1, p :1, pre :1, li :1, dt :1, de :1, div :1, td:1, th:1
     13        };
     14       
    815        var guardDomWalkerNonEmptyTextNode = function( evt )
    916        {
    10                 if ( evt.data.to && evt.data.to.type == CKEDITOR.NODE_TEXT && evt.data.to.$.length > 0 )
     17                if ( evt.data.to && evt.data.to.type == CKEDITOR.NODE_TEXT
     18                        && evt.data.to.$.length > 0 )
    1119                        this.stop();
    1220                CKEDITOR.dom.domWalker.blockBoundary( { br : 1 } ).call( this, evt );
    1321        };
    14 
    15         var domWalkerEventBridge = function()
    16         {
    17                 var me = this,
    18                         handler = function( evt ){ me.fire( evt.data.type, evt.data ); me._.actionEvents.push( evt.data ); };
    19                 this._.walker.on( 'up', handler );
    20                 this._.walker.on( 'down', handler );
    21                 this._.walker.on( 'sibling', handler );
    22         };
    23 
    24         var fireCharacterEvent = function()
     22       
     23       
     24        /**
     25         * Get the cursor object which represent both current character and it's dom
     26         * position thing.
     27         */
     28        var getCurrentCursor = function()
    2529        {
    2630                var obj = {
    27                         type : 'character',
     31                        textNode : this.textNode,
     32                        offset : this.offset,
    2833                        character : this.textNode ? this.textNode.getText().charAt( this.offset ) : null,
    2934                        hitMatchBoundary : this._.matchBoundary
    3035                };
    31                 this.fire( 'character', obj );
    32                 this._.actionEvents.push( obj );
    33                 return { character : obj.character, events : this._.actionEvents };
     36                return obj;
    3437        };
     38       
     39        var pages = [ 'find', 'replace' ],
     40                fieldsMapping = [
     41                [ 'txtFindFind', 'txtFindReplace' ],
     42                [ 'txtFindCaseChk', 'txtReplaceCaseChk' ],
     43                [ 'txtFindWordChk', 'txtReplaceWordChk' ],
     44                [ 'txtFindCyclic', 'txtReplaceCyclic' ] ],
     45               
     46        /**
     47         * Synchronize corresponding filed values between 'replace' and 'find' pages.
     48         * @param {String} currentPageId        The page id which receive values.
     49         */
     50        function syncFieldsBetweenTabs( currentPageId)
     51        {
     52                        var sourceIndex, targetIndex,
     53                                sourceField, targetField;
     54               
     55                        sourceIndex = currentPageId === 'find' ? 1 : 0;
     56                        targetIndex = 1 - sourceIndex;
     57                        var i, l = fieldsMapping.length;
     58                        for ( i = 0 ; i < l ; i++ )
     59                        {
     60                                var sourceField = this
     61                                        .getContentElement( pages[ sourceIndex ],
     62                                                fieldsMapping[ i ][ sourceIndex ] ),
     63                                        targetField = this
     64                                        .getContentElement( pages[ targetIndex ],
     65                                                fieldsMapping[ i ][ targetIndex ] );
     66                               
     67                                targetField.setValue( sourceField.getValue() );
     68                        }
     69        }
    3570
    3671        var findDialog = function( editor, startupPage )
    3772        {
    38                 var characterWalker = function( cursorOrTextNode, offset )
     73                //back refer the dialog instance.
     74                var dialog;
     75               
     76                /**
     77                 * Iterator which walk through document char by char.
     78                 * @param {Object} start
     79                 * @param {Number} offset
     80                 */
     81                var characterWalker = function( start, offset )
    3982                {
    40                         var isCursor = ( cursorOrTextNode instanceof characterWalker );
     83                        var isCursor = typeof start.textNode !== 'undefined';
     84                        this.textNode = isCursor ? start.textNode : start;
     85                        this.offset = isCursor ? start.offset : offset;
    4186                        this._ = {
    42                                 matchBoundary : false,
    43                                 actionEvents : null
     87                                walker : new CKEDITOR.dom.domWalker( this.textNode ),
     88                                matchBoundary : false
    4489                        };
    45                         this.textNode = isCursor ? cursorOrTextNode.textNode : cursorOrTextNode,
    46                         this.offset = isCursor ? cursorOrTextNode.offset : offset,
    47                         this._.walker = new CKEDITOR.dom.domWalker( this.textNode );
    48                         CKEDITOR.event.implementOn( this );
    49                         domWalkerEventBridge.call( this );
    5090                };
    5191
    5292                characterWalker.prototype = {
     
    5292                characterWalker.prototype = {
    5393                        next : function()
    5494                        {
    55                                 // Clear any previous action events and related flags.
    56                                 this._.actionEvents = [];
     95                                // Already at the end of document, no more character available.
     96                                if( this.textNode === null && this._.matchBoundary )
     97                                        return getCurrentCursor.call( this );
     98                                       
    5799                                this._.matchBoundary = false;
    58 
    59                                 // If there are more characters in the text node, get it and raise an event.
    60                                 if ( this.textNode.type == CKEDITOR.NODE_TEXT && this.offset < this.textNode.getLength() - 1 )
     100                               
     101                                // If there are more characters in the text node, get it and
     102                                // raise an event.
     103                                if( this.textNode.type == CKEDITOR.NODE_TEXT
     104                                        && this.offset < this.textNode.getLength() - 1 )
    61105                                {
    62106                                        this.offset++;
    63                                         return fireCharacterEvent.call( this );
     107                                        return getCurrentCursor.call( this );
    64108                                }
    65109
    66                                 // If we are at the end of the text node, use dom walker to get the next text node.
     110                                // If we are at the end of the text node, use dom walker to get
     111                                // the next text node.
    67112                                var data = null;
    68                                 while ( !data || ( data.node && data.node.type != CKEDITOR.NODE_TEXT ) )
     113                                while ( !data || ( data.node && data.node.type !=
     114                                        CKEDITOR.NODE_TEXT ) )
    69115                                {
    70                                         data = this._.walker.forward( guardDomWalkerNonEmptyTextNode );
    71 
     116                                        data = this._.walker.forward(
     117                                                guardDomWalkerNonEmptyTextNode );
     118       
    72119                                        // Block boundary? BR? Document boundary?
    73                                         if ( !data.node || data.node.type != CKEDITOR.NODE_TEXT )
     120                                        if ( !data.node
     121                                                || ( data.node.type !== CKEDITOR.NODE_TEXT
     122                                                        && data.node.getName() in
     123                                                        characterBoundaryElementsEnum ) )
    74124                                                this._.matchBoundary = true;
    75125                                }
    76126                                this.textNode = data.node;
     
    75125                                }
    76126                                this.textNode = data.node;
    77127                                this.offset = 0;
    78                                 return fireCharacterEvent.call( this );
     128                                return getCurrentCursor.call( this );
    79129                        },
    80 
     130                       
    81131                        back : function()
    82132                        {
    83                                 // Clear any previous action events and related flags.
    84                                 this._.actionEvents = [];
    85133                                this._.matchBoundary = false;
    86134
    87135                                // More characters -> decrement offset and return.
     
    88136                                if ( this.textNode.type == CKEDITOR.NODE_TEXT && this.offset > 0 )
    89137                                {
    90138                                        this.offset--;
    91                                         return fireCharacterEvent.call( this );
     139                                        return getCurrentCursor.call( this );
    92140                                }
    93141
    94142                                // Start of text node -> use dom walker to get the previous text node.
     
    93141
    94142                                // Start of text node -> use dom walker to get the previous text node.
    95143                                var data = null;
    96                                 while ( !data || ( data.node && data.node.type != CKEDITOR.NODE_TEXT ) )
     144                                while ( !data
     145                                || ( data.node && data.node.type != CKEDITOR.NODE_TEXT ) )
    97146                                {
    98147                                        data = this._.walker.reverse( guardDomWalkerNonEmptyTextNode );
    99148
     
    98147                                        data = this._.walker.reverse( guardDomWalkerNonEmptyTextNode );
    99148
    100149                                        // Block boundary? BR? Document boundary?
    101                                         if ( !data.node || data.node.type != CKEDITOR.NODE_TEXT )
     150                                        if ( !data.node || ( data.node.type !== CKEDITOR.NODE_TEXT &&
     151                                        data.node.getName() in characterBoundaryElementsEnum ) )
    102152                                                this._.matchBoundary = true;
    103153                                }
    104154                                this.textNode = data.node;
     
    103153                                }
    104154                                this.textNode = data.node;
    105155                                this.offset = data.node.length - 1;
    106                                 return fireCharacterEvent.call( this );
    107                         },
    108 
    109                         getChar : function()
    110                         {
    111                                 return this.textNode ? this.textNode.getText().charAt( this.offset ) : null;
     156                                return getCurrentCursor.call( this );
    112157                        }
    113158                };
    114 
    115                 var characterRange = function( initCursor, maxLength )
     159               
     160                /**
     161                 * A range of cursors which represent a trunk of characters which try to
     162                 * match, it has the same length as the pattern  string.
     163                 */
     164                var characterRange = function( characterWalker, rangeLength )
    116165                {
    117166                        this._ = {
    118                                 cursors : initCursor.push ? initCursor : [ initCursor ],
    119                                 maxLength : maxLength,
    120                                 highlightRange : null
     167                                walker : characterWalker,
     168                                cursors : [],
     169                                rangeLength : rangeLength,
     170                                highlightRange : null,
     171                                isMatched : false
    121172                        };
    122173                };
    123174
     
    122173                };
    123174
    124175                characterRange.prototype = {
     176                        /**
     177                         * Translate this range to {@link CKEDITOR.dom.range}
     178                         */
    125179                        toDomRange : function()
    126180                        {
    127181                                var cursors = this._.cursors;
     
    136190                                range.setEnd( last.textNode, last.offset + 1 );
    137191                                return range;
    138192                        },
    139 
     193                       
     194                        setMatched : function()
     195                        {
     196                                this._.isMatched = true;
     197                                this.highlight();
     198                        },
     199                       
     200                        clearMatched : function()
     201                        {
     202                                this._.isMatched = false;
     203                                this.removeHighlight();
     204                        },
     205                       
     206                        isMatched : function()
     207                        {
     208                                return this._.isMatched;
     209                        },
     210                       
     211                        /**
     212                         * Hightlight the current matched chunk of text, using selection
     213                         * system to represent highlight until marking-style is implemented.
     214                         */
    140215                        highlight : function()
    141216                        {
    142                                 // TODO: wait till Fred has implemented style removal for this.
     217                                if(CKEDITOR.env.ie)
     218                                        dialog.restoreSelection();
     219                               
    143220                                editor.getSelection().selectRanges( [ this.toDomRange() ] );
     221                               
     222                                if(CKEDITOR.env.ie)
     223                                {
     224                                        dialog.saveSelection();
     225                                       
     226                                        // since IE broke text nodes, update these changes back to
     227                                        // character range.
     228                                        var dirtyRange = editor.getSelection().getRanges()[0];
     229                                        var cursors = this._.cursors;
     230                                        var first = cursors[0],
     231                                        last = cursors[ cursors.length - 1 ];
     232                                        first.textNode = dirtyRange.startContainer;
     233                                        first.offset = dirtyRange.startOffset;
     234                                        last.textNode = dirtyRange.endContainer;
     235                                        last.offset = dirtyRange.endOffset;
     236                                }
    144237                        },
    145 
     238                       
     239                        /**
     240                         * Wait for highlight marking-style in order to perform removal.
     241                         */
    146242                        removeHighlight : function()
    147243                        {
    148                                 // TODO: wait till Fred has implemented style removal for this.
     244                                this._.highlightRange = null;
    149245                        },
    150246
    151                         getHighlightDomRange : function()
     247                        moveBack : function()
    152248                        {
    153                                 // TODO: wait till Fred has implemented style removal for this.
    154                                 return this.toDomRange();
    155                         },
    156 
    157                         moveNext : function()
    158                         {
    159                                 var next = new characterWalker( this._.cursors[ this._.cursors.length - 1 ] ),
    160                                         retval = next.next(),
     249                                var retval = this._.walker.back(),
    161250                                        cursors = this._.cursors;
    162251
    163                                 // Clear the cursors queue if we've crossed a match boundary.
    164252                                if ( retval.hitMatchBoundary )
    165253                                        this._.cursors = cursors = [];
    166254
    167                                 cursors.push( next );
    168                                 if ( cursors.length > this._.maxLength )
    169                                         cursors.shift();
     255                                cursors.unshift( retval );
     256                                if ( cursors.length > this._.rangeLength )
     257                                        cursors.pop();
    170258
    171259                                return retval;
    172260                        },
    173 
    174                         moveBack : function()
     261       
     262                        moveNext : function()
    175263                        {
    176                                 var prev = new characterWalker( this._.cursors[0] ),
    177                                         retval = prev.back(),
     264                                var retval = this._.walker.next(),
    178265                                        cursors = this._.cursors;
    179266
     267                                // Clear the cursors queue if we've crossed a match boundary.
    180268                                if ( retval.hitMatchBoundary )
    181269                                        this._.cursors = cursors = [];
    182270
    183                                 cursors.unshift( prev );
    184                                 if ( cursors.length > this._.maxLength )
    185                                         cursors.pop();
     271                                cursors.push( retval );
     272                                if ( cursors.length > this._.rangeLength )
     273                                        cursors.shift();
    186274
    187275                                return retval;
    188276                        },
     
    193281                                if ( cursors.length < 1 )
    194282                                        return null;
    195283
    196                                 return cursors[ cursors.length - 1 ].getChar();
     284                                return cursors[ cursors.length - 1 ].character;
    197285                        },
    198286
    199                         getNextRange : function( maxLength )
     287                        updateRange : function( newrangeLength )
    200288                        {
    201                                 var cursors = this._.cursors;
    202                                 if ( cursors.length < 1 )
    203                                         return null;
    204 
    205                                 var next = new characterWalker( cursors[ cursors.length - 1 ] );
    206                                 next.next();
    207                                 return new characterRange( next, maxLength );
     289                                this._.cursors = [];
     290                                this._.rangeLength = newrangeLength;
     291                                this.removeHighlight();
    208292                        },
    209293
    210294                        getCursors : function()
     
    216300                var KMP_NOMATCH = 0,
    217301                        KMP_ADVANCED = 1,
    218302                        KMP_MATCHED = 2;
     303                /**
     304                 * Examination the occurrence of a word which implement KMP algorithm.
     305                 */
    219306                var kmpMatcher = function( pattern, ignoreCase )
    220307                {
    221308                        var overlap = [ -1 ];
     
    224311                        for ( var i = 0 ; i < pattern.length ; i++ )
    225312                        {
    226313                                overlap.push( overlap[i] + 1 );
    227                                 while ( overlap[ i + 1 ] > 0 && pattern.charAt( i ) != pattern.charAt( overlap[ i + 1 ] - 1 ) )
     314                                while ( overlap[ i + 1 ] > 0
     315                                        && pattern.charAt( i ) != pattern
     316                                                .charAt( overlap[ i + 1 ] - 1 ) )
    228317                                        overlap[ i + 1 ] = overlap[ overlap[ i + 1 ] - 1 ] + 1;
    229318                        }
    230319
     
    268357                        }
    269358                };
    270359
    271                 var wordSeparatorRegex = /[.,"'?!;: \u0085\u00a0\u1680\u280e\u2028\u2029\u202f\u205f\u3000]/,
     360                var wordSeparatorRegex =
     361                /[.,"'?!;: \u0085\u00a0\u1680\u280e\u2028\u2029\u202f\u205f\u3000]/,
    272362                        isWordSeparator = function( c )
    273363                        {
    274364                                if ( !c )
     
    274364                                if ( !c )
    275365                                        return true;
    276366                                var code = c.charCodeAt( 0 );
    277                                 return ( code >= 9 && code <= 0xd ) || ( code >= 0x2000 && code <= 0x200a ) || wordSeparatorRegex.test( c );
     367                                return ( code >= 9 && code <= 0xd )
     368                                || ( code >= 0x2000 && code <= 0x200a )
     369                                || wordSeparatorRegex.test( c );
    278370                        };
    279371
    280372                var finder = {
     373                        startCursor : null,
    281374                        range : null,
    282                         find : function( pattern, matchCase, matchWord )
     375                        find : function( pattern, matchCase, matchWord, matchCyclic )
    283376                        {
    284                                 if ( !this.range )
    285                                         this.range = new characterRange( new characterWalker( editor.document.getBody(), 0 ), pattern.length );
     377                                if( !this.range )
     378                                        this.range = new characterRange( new characterWalker(
     379                                                this.startCursor ) , pattern.length );
    286380                                else
    287381                                {
    288                                         this.range.removeHighlight();
    289                                         this.range = this.range.getNextRange( pattern.length );
     382                                        this.range.updateRange( pattern.length );
    290383                                }
    291384
    292385                                var matcher = new kmpMatcher( pattern, !matchCase ),
     
    295388
    296389                                while ( character != null )
    297390                                {
     391                                        this.range.moveNext();
    298392                                        while ( ( character = this.range.getEndCharacter() ) )
    299393                                        {
    300394                                                matchState = matcher.feedCharacter( character );
     
    309403                                                if ( matchWord )
    310404                                                {
    311405                                                        var cursors = this.range.getCursors(),
    312                                                                 head = new characterCursor( cursors[ cursors.length - 1 ] ),
    313                                                                 tail = new characterCursor( cursors[0] );
    314                                                         if ( !( head.next().character || isWordSeparator( head.getChar() ) ) )
    315                                                                 continue;
    316                                                         if ( !( tail.back().character || isWordSeparator( tail.getChar() ) ) )
     406                                                                tail = cursors[ cursors.length - 1 ],
     407                                                                head = cursors[ 0 ],
     408                                                                headWalker = new characterWalker(head),
     409                                                                tailWalker = new characterWalker(tail);
     410                                                               
     411                                                        if ( ! ( isWordSeparator(
     412                                                                                headWalker.back().character )
     413                                                                                && isWordSeparator(
     414                                                                                tailWalker.next().character ) ) )
    317415                                                                continue;
    318416                                                }
    319417
    320                                                 this.range.highlight();
     418                                                this.range.setMatched();
    321419                                                return true;
    322420                                        }
    323421                                }
     422                               
     423                                this.range.clearMatched();
     424                               
     425                                // clear current session and restart from beginning
     426                                if ( matchCyclic )
     427                                        this.range = null;
     428                               
     429                                return false;
     430                        },
     431                       
     432                        /**
     433                         * Record how much replacement occurred toward one replacing.
     434                         */
     435                        replaceCounter : 0,
     436                       
     437                        replace : function( pattern, newString, matchCase, matchWord,
     438                                matchCyclic, matchReplaceAll )
     439                        {
     440                                var replaceResult = false;
     441                                if ( this.range && this.range.isMatched() )
     442                                {
     443                                        if ( CKEDITOR.env.ie )
     444                                                dialog.restoreSelection();
    324445
    325                                 this.range = null;
    326                                 return false;
     446                                        var domrange = this.range.toDomRange();
     447                                        var documentFragment = domrange.extractContents();
     448                                        // Use the first text container as holder, no matter what
     449                                        // kind of element it is.
     450                                        var contentHolder = documentFragment.getFirst();
     451
     452                                        if ( contentHolder.type === CKEDITOR.NODE_ELEMENT )
     453                                                contentHolder.setText( newString );
     454                                        else
     455                                                contentHolder = editor.document.createText( newString );
     456
     457                                        domrange.insertNode( contentHolder );
     458
     459                                        if ( CKEDITOR.env.ie )
     460                                                dialog.saveSelection();
     461
     462                                        this.replaceCounter++;
     463                                        replaceResult = true;
     464                                }
     465                               
     466                                var findResult = this.find(
     467                                        pattern, matchCase, matchWord,  matchCyclic );
     468                                if ( findResult && matchReplaceAll )
     469                                {
     470                                        this.replace.apply( this,
     471                                                Array.prototype.slice.call( arguments ) );
     472                                }
     473                                return matchReplaceAll ?
     474                                        this.replaceCounter : replaceResult || findResult;
    327475                        }
     476                       
    328477                };
     478               
     479                /**
     480                 * Get the default cursor which is the start of this document.
     481                 */
     482                function getDefaultStartCursor()
     483                {
     484                        return {textNode : editor.document.getBody(), offset: 0};
     485                }
     486               
     487                /**
     488                 * Get cursor that indicate search begin with, receive from user
     489                 * selection prior.
     490                 */
     491                function getStartCursor()
     492                {
     493                        if ( CKEDITOR.env.ie )
     494                                dialog.restoreSelection();
    329495
     496                        var sel = editor.getSelection();
     497                        if ( sel )
     498                        {
     499                                var lastRange = sel.getRanges()[ sel.getRanges().length - 1 ];
     500                                return {
     501                                        textNode : lastRange.getBoundaryNodes().endNode,
     502                                        offset : lastRange.endContainer.type ===
     503                                                CKEDITOR.NODE_ELEMENT ?
     504                                                0       : lastRange.endOffset
     505                                };
     506                        }
     507                        else
     508                                return getDefaultStartCursor();
     509                }
     510               
    330511                return {
    331512                        title : editor.lang.findAndReplace.title,
    332513                        resizable : CKEDITOR.DIALOG_RESIZE_NONE,
     
    331512                        title : editor.lang.findAndReplace.title,
    332513                        resizable : CKEDITOR.DIALOG_RESIZE_NONE,
    333514                        minWidth : 400,
    334                         minHeight : 245,
     515                        minHeight : 255,
    335516                        buttons : [ CKEDITOR.dialog.cancelButton ],             //Cancel button only.
    336517                        contents : [
    337518                                {
     
    351532                                                                        label : editor.lang.findAndReplace.findWhat,
    352533                                                                        isChanged : false,
    353534                                                                        labelLayout : 'horizontal',
    354                                                                         accessKey : 'F',
     535                                                                        accessKey : 'F'
    355536                                                                },
    356537                                                                {
    357538                                                                        type : 'button',
     
    361542                                                                        onClick : function()
    362543                                                                        {
    363544                                                                                var dialog = this.getDialog();
    364                                                                                 if ( !finder.find( dialog.getValueOf( 'find', 'txtFindFind' ),
    365                                                                                                         dialog.getValueOf( 'find', 'txtFindCaseChk' ),
    366                                                                                                         dialog.getValueOf( 'find', 'txtFindWordChk' ) ) )
    367                                                                                         alert( editor.lang.findAndReplace.notFoundMsg );
     545                                                                                if ( !finder.find( dialog.getValueOf(
     546                                                                                        'find', 'txtFindFind' ), dialog
     547                                                                                        .getValueOf( 'find',
     548                                                                                                'txtFindCaseChk' ), dialog
     549                                                                                        .getValueOf( 'find',
     550                                                                                                'txtFindWordChk' ), dialog
     551                                                                                        .getValueOf( 'find',
     552                                                                                                'txtFindCyclic' ) ) )
     553                                                                                        alert( editor.lang.findAndReplace
     554                                                                                                .notFoundMsg );
    368555                                                                        }
    369                                                                 },
     556                                                                }
    370557                                                        ]
    371558                                                },
    372559                                                {
     
    374561                                                        id : 'txtFindCaseChk',
    375562                                                        isChanged : false,
    376563                                                        style : 'margin-top:28px',
    377                                                         label : editor.lang.findAndReplace.matchCase,
     564                                                        label : editor.lang.findAndReplace.matchCase
    378565                                                },
    379566                                                {
    380567                                                        type : 'checkbox',
     
    380567                                                        type : 'checkbox',
    381568                                                        id : 'txtFindWordChk',
    382569                                                        isChanged : false,
    383                                                         label : editor.lang.findAndReplace.matchWord,
     570                                                        label : editor.lang.findAndReplace.matchWord
    384571                                                },
    385572                                                {
    386573                                                        type : 'checkbox',
     
    387574                                                        id : 'txtFindCyclic',
    388575                                                        isChanged : false,
    389576                                                        checked : true,
    390                                                         label : editor.lang.findAndReplace.matchCyclic,
    391                                                 },
     577                                                        label : editor.lang.findAndReplace.matchCyclic
     578                                                }
    392579                                        ]
    393580                                },
    394581                                {
     
    407594                                                                        label : editor.lang.findAndReplace.findWhat,
    408595                                                                        isChanged : false,
    409596                                                                        labelLayout : 'horizontal',
    410                                                                         accessKey : 'F',
     597                                                                        accessKey : 'F'
    411598                                                                },
    412599                                                                {
    413600                                                                        type : 'button',
     
    416603                                                                        label : editor.lang.findAndReplace.replace,
    417604                                                                        onClick : function()
    418605                                                                        {
    419                                                                                 alert( editor.lang.findAndReplace.notFoundMsg );
     606                                                                                var dialog = this.getDialog();
     607                                                                                if ( !finder.replace( dialog
     608                                                                                        .getValueOf( 'replace',
     609                                                                                                'txtFindReplace' ), dialog
     610                                                                                        .getValueOf( 'replace',
     611                                                                                                'txtReplace' ), dialog
     612                                                                                        .getValueOf( 'replace',
     613                                                                                                'txtReplaceCaseChk' ), dialog
     614                                                                                        .getValueOf( 'replace',
     615                                                                                                'txtReplaceWordChk' ), dialog
     616                                                                                        .getValueOf( 'replace',
     617                                                                                                'txtReplaceCyclic' ) ) )
     618                                                                                        alert( editor.lang.findAndReplace
     619                                                                                                .notFoundMsg );
    420620                                                                        }
    421                                                                 },
     621                                                                }
    422622                                                        ]
    423623                                                },
    424624                                                {
     
    429629                                                                {
    430630                                                                        type : 'text',
    431631                                                                        id : 'txtReplace',
    432                                                                         label : editor.lang.findAndReplace.replaceWith,
     632                                                                        label : editor.lang.findAndReplace
     633                                                                        .replaceWith,
    433634                                                                        isChanged : false,
    434635                                                                        labelLayout : 'horizontal',
    435                                                                         accessKey : 'R',
     636                                                                        accessKey : 'R'
    436637                                                                },
    437638                                                                {
    438639                                                                        type : 'button',
     
    438639                                                                        type : 'button',
    439640                                                                        align : 'left',
    440641                                                                        style : 'width:100%',
    441                                                                         label : editor.lang.findAndReplace.replaceAll,
     642                                                                        label : editor.lang.findAndReplace
     643                                                                                .replaceAll,
    442644                                                                        isChanged : false,
    443645                                                                        onClick : function()
    444646                                                                        {
    445                                                                                 alert( editor.lang.findAndReplace.notFoundMsg );
     647                                                                                var dialog = this.getDialog();
     648                                                                                var replaceNums;
     649
     650                                                                                finder.replaceCounter = 0;
     651                                                                                if ( ( replaceNums = finder.replace(
     652                                                                                        dialog.getValueOf( 'replace',
     653                                                                                                'txtFindReplace' ), dialog
     654                                                                                                .getValueOf( 'replace',
     655                                                                                                        'txtReplace' ), dialog
     656                                                                                                .getValueOf( 'replace',
     657                                                                                                        'txtReplaceCaseChk' ),
     658                                                                                        dialog.getValueOf( 'replace',
     659                                                                                                'txtReplaceWordChk' ), dialog
     660                                                                                                .getValueOf( 'replace',
     661                                                                                                        'txtReplaceCyclic' ), true ) ) )
     662                                                                                        alert( editor.lang.findAndReplace
     663                                                                                                .replaceSuccMsg
     664                                                                                                .replace( /%1/, replaceNums ) );
     665                                                                                else
     666                                                                                        alert( editor.lang.findAndReplace
     667                                                                                                .notFoundMsg );
    446668                                                                        }
    447                                                                 },
     669                                                                }
    448670                                                        ]
    449671                                                },
    450672                                                {
     
    451673                                                        type : 'checkbox',
    452674                                                        id : 'txtReplaceCaseChk',
    453675                                                        isChanged : false,
    454                                                         label : editor.lang.findAndReplace.matchCase,
     676                                                        label : editor.lang.findAndReplace
     677                                                                .matchCase
    455678                                                },
    456679                                                {
    457680                                                        type : 'checkbox',
     
    457680                                                        type : 'checkbox',
    458681                                                        id : 'txtReplaceWordChk',
    459682                                                        isChanged : false,
    460                                                         label : editor.lang.findAndReplace.matchWord,
     683                                                        label : editor.lang.findAndReplace
     684                                                                .matchWord
    461685                                                },
    462686                                                {
    463687                                                        type : 'checkbox',
     
    464688                                                        id : 'txtReplaceCyclic',
    465689                                                        isChanged : false,
    466690                                                        checked : true,
    467                                                         label : editor.lang.findAndReplace.matchCyclic,
    468                                                 },
     691                                                        label : editor.lang.findAndReplace
     692                                                                .matchCyclic
     693                                                }
    469694                                        ]
    470695                                }
    471696                        ],
     697                        onLoad : function()
     698                        {
     699                                dialog = this;
     700                               
     701                                //keep trac of the current pattern field in use.
     702                                var patternField, wholeWordChkField;
     703                               
     704                                /**
     705                                 * Check the whether the 'wholeworld' match mode could be
     706                                 * toggled on.
     707                                 */
     708                                function checkWholeWordState()
     709                                {
     710                                        var isWord = /^\w+$/.test( patternField.getValue() );
     711                                        var wholeWordChkFieldEl = wholeWordChkField.getElement();
     712                                        if ( isWord )
     713                                                wholeWordChkFieldEl.show();
     714                                        else
     715                                                wholeWordChkFieldEl.hide();
     716                                }
     717                               
     718                                //Ignore initial page select on dialog show
     719                                var isUserSelect = false;
     720                                this.on('hide', function(){
     721                                        isUserSelect = false;
     722                                });
     723                                this.on('show', function(){
     724                                        isUserSelect = true;
     725                                });
     726                               
     727                                this.selectPage = CKEDITOR.tools.override( this.selectPage,
     728                                        function( originalFunc )
     729                                        {
     730                                                return function( pageId )
     731                                                {
     732                                                        originalFunc.call( dialog, pageId );
     733                                                       
     734                                                        var currPage = dialog._.tabs[ pageId ];
     735                                                        var patternFieldInput, patternFieldId, wholeWordChkFieldId;
     736                                                        patternFieldId = pageId === 'find' ? 'txtFindFind'
     737                                                                : 'txtFindReplace';
     738                                                        wholeWordChkFieldId = pageId === 'find' ? 'txtFindWordChk'
     739                                                                : 'txtReplaceWordChk';
     740
     741                                                        patternField = dialog.getContentElement( pageId,
     742                                                                patternFieldId );
     743                                                        wholeWordChkField = dialog.getContentElement( pageId,
     744                                                                wholeWordChkFieldId );
     745                                                       
     746                                                        // prepare for check pattern text filed 'keyup' event
     747                                                        if ( !currPage.initialized )
     748                                                        {
     749                                                                patternFieldInput = CKEDITOR.document
     750                                                                        .getById( patternField._.inputId );
     751                                                                patternFieldInput.on( 'keyup', checkWholeWordState );
     752                                                                currPage.initialized = true;
     753                                                        }
     754                                                       
     755                                                        if(isUserSelect)
     756                                                                // synchronize fields on tab switch.
     757                                                                syncFieldsBetweenTabs.call( this, pageId );
     758                                                       
     759                                                        //check wholeword match status on tab switch
     760                                                        checkWholeWordState();
     761                                };
     762                        } );
     763
     764                        },
    472765                        onShow : function()
    473766                        {
     767                                //Establish initial searching start position.
     768                                finder.startCursor = getStartCursor();
     769                               
    474770                                if ( startupPage == 'replace' )
    475771                                        this.getContentElement( 'replace', 'txtFindReplace' ).focus();
    476772                                else
     
    478774                        },
    479775                        onHide : function()
    480776                        {
    481                                 if ( finder.range )
     777                                if ( finder.range && finder.range.isMatched() )
    482778                                {
    483                                         finder.range.removeHighlight();
    484                                         editor.getSelection().selectRanges( [finder.range.toDomRange()] );
     779                                        editor.getSelection().selectRanges(
     780                                                [ finder.range.toDomRange() ] );
    485781                                }
     782                                //clear current session before dialog close
     783                                delete finder.range;
    486784                        }
    487785                };
    488786        };
  • _source/core/dom/document.js

     
    7070
    7171                createText : function( text )
    7272                {
    73                         return new CKEDITOR.dom.text( '', this );
     73                        return new CKEDITOR.dom.text( text, this );
    7474                },
    7575
    7676                /**
  • _source/core/config.js

     
    147147         * config.plugins = 'basicstyles,button,htmldataprocessor,toolbar,wysiwygarea';
    148148         */
    149149
    150         plugins : 'basicstyles,button,elementspath,horizontalrule,htmldataprocessor,keystrokes,newpage,pagebreak,preview,removeformat,smiley,indent,link,list,justify,blockquote,sourcearea,table,specialchar,tab,toolbar,wysiwygarea',
     150        plugins : 'basicstyles,button,elementspath,horizontalrule,htmldataprocessor,keystrokes,newpage,pagebreak,preview,removeformat,smiley,indent,link,list,sourcearea,table,specialchar,tab,toolbar,wysiwygarea,find',
    151151
    152152        /**
    153153         * The theme to be used to build the UI.
© 2003 – 2022, CKSource sp. z o.o. sp.k. All rights reserved. | Terms of use | Privacy policy