source: trunk/admin/inc/ckeditor/_source/plugins/find/dialogs/find.js@ 239

Last change on this file since 239 was 239, checked in by luc, 9 years ago

Admin: correzione visulaizzazione immissione dati spoglio per Chrome e Safari - Aggiornamento dell'editor da FCKeditor a CKeditor , accessibili anche a Chrome e Safari.

  • Property svn:executable set to *
File size: 24.1 KB
Line 
1/*
2Copyright (c) 2003-2011, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.html or http://ckeditor.com/license
4*/
5
6(function()
7{
8 var isReplace;
9
10 function findEvaluator( node )
11 {
12 return node.type == CKEDITOR.NODE_TEXT && node.getLength() > 0 && ( !isReplace || !node.isReadOnly() );
13 }
14
15 /**
16 * Elements which break characters been considered as sequence.
17 */
18 function nonCharactersBoundary( node )
19 {
20 return !( node.type == CKEDITOR.NODE_ELEMENT && node.isBlockBoundary(
21 CKEDITOR.tools.extend( {}, CKEDITOR.dtd.$empty, CKEDITOR.dtd.$nonEditable ) ) );
22 }
23
24 /**
25 * Get the cursor object which represent both current character and it's dom
26 * position thing.
27 */
28 var cursorStep = function()
29 {
30 return {
31 textNode : this.textNode,
32 offset : this.offset,
33 character : this.textNode ?
34 this.textNode.getText().charAt( this.offset ) : null,
35 hitMatchBoundary : this._.matchBoundary
36 };
37 };
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 sourceField = this.getContentElement( pages[ sourceIndex ],
61 fieldsMapping[ i ][ sourceIndex ] );
62 targetField = this.getContentElement( pages[ targetIndex ],
63 fieldsMapping[ i ][ targetIndex ] );
64
65 targetField.setValue( sourceField.getValue() );
66 }
67 }
68
69 var findDialog = function( editor, startupPage )
70 {
71 // Style object for highlights: (#5018)
72 // 1. Defined as full match style to avoid compromising ordinary text color styles.
73 // 2. Must be apply onto inner-most text to avoid conflicting with ordinary text color styles visually.
74 var highlightStyle = new CKEDITOR.style(
75 CKEDITOR.tools.extend( { attributes : { 'data-cke-highlight': 1 }, fullMatch : 1, ignoreReadonly : 1, childRule : function(){ return 0; } },
76 editor.config.find_highlight, true ) );
77
78 /**
79 * Iterator which walk through the specified range char by char. By
80 * default the walking will not stop at the character boundaries, until
81 * the end of the range is encountered.
82 * @param { CKEDITOR.dom.range } range
83 * @param {Boolean} matchWord Whether the walking will stop at character boundary.
84 */
85 var characterWalker = function( range , matchWord )
86 {
87 var self = this;
88 var walker =
89 new CKEDITOR.dom.walker( range );
90 walker.guard = matchWord ? nonCharactersBoundary : function( node )
91 {
92 !nonCharactersBoundary( node ) && ( self._.matchBoundary = true );
93 };
94 walker[ 'evaluator' ] = findEvaluator;
95 walker.breakOnFalse = 1;
96
97 if ( range.startContainer.type == CKEDITOR.NODE_TEXT )
98 {
99 this.textNode = range.startContainer;
100 this.offset = range.startOffset - 1;
101 }
102
103 this._ = {
104 matchWord : matchWord,
105 walker : walker,
106 matchBoundary : false
107 };
108 };
109
110 characterWalker.prototype = {
111 next : function()
112 {
113 return this.move();
114 },
115
116 back : function()
117 {
118 return this.move( true );
119 },
120
121 move : function( rtl )
122 {
123 var currentTextNode = this.textNode;
124 // Already at the end of document, no more character available.
125 if ( currentTextNode === null )
126 return cursorStep.call( this );
127
128 this._.matchBoundary = false;
129
130 // There are more characters in the text node, step forward.
131 if ( currentTextNode
132 && rtl
133 && this.offset > 0 )
134 {
135 this.offset--;
136 return cursorStep.call( this );
137 }
138 else if ( currentTextNode
139 && this.offset < currentTextNode.getLength() - 1 )
140 {
141 this.offset++;
142 return cursorStep.call( this );
143 }
144 else
145 {
146 currentTextNode = null;
147 // At the end of the text node, walking foward for the next.
148 while ( !currentTextNode )
149 {
150 currentTextNode =
151 this._.walker[ rtl ? 'previous' : 'next' ].call( this._.walker );
152
153 // Stop searching if we're need full word match OR
154 // already reach document end.
155 if ( this._.matchWord && !currentTextNode
156 || this._.walker._.end )
157 break;
158 }
159 // Found a fresh text node.
160 this.textNode = currentTextNode;
161 if ( currentTextNode )
162 this.offset = rtl ? currentTextNode.getLength() - 1 : 0;
163 else
164 this.offset = 0;
165 }
166
167 return cursorStep.call( this );
168 }
169
170 };
171
172 /**
173 * A range of cursors which represent a trunk of characters which try to
174 * match, it has the same length as the pattern string.
175 */
176 var characterRange = function( characterWalker, rangeLength )
177 {
178 this._ = {
179 walker : characterWalker,
180 cursors : [],
181 rangeLength : rangeLength,
182 highlightRange : null,
183 isMatched : 0
184 };
185 };
186
187 characterRange.prototype = {
188 /**
189 * Translate this range to {@link CKEDITOR.dom.range}
190 */
191 toDomRange : function()
192 {
193 var range = new CKEDITOR.dom.range( editor.document );
194 var cursors = this._.cursors;
195 if ( cursors.length < 1 )
196 {
197 var textNode = this._.walker.textNode;
198 if ( textNode )
199 range.setStartAfter( textNode );
200 else
201 return null;
202 }
203 else
204 {
205 var first = cursors[0],
206 last = cursors[ cursors.length - 1 ];
207
208 range.setStart( first.textNode, first.offset );
209 range.setEnd( last.textNode, last.offset + 1 );
210 }
211
212 return range;
213 },
214 /**
215 * Reflect the latest changes from dom range.
216 */
217 updateFromDomRange : function( domRange )
218 {
219 var cursor,
220 walker = new characterWalker( domRange );
221 this._.cursors = [];
222 do
223 {
224 cursor = walker.next();
225 if ( cursor.character )
226 this._.cursors.push( cursor );
227 }
228 while ( cursor.character );
229 this._.rangeLength = this._.cursors.length;
230 },
231
232 setMatched : function()
233 {
234 this._.isMatched = true;
235 },
236
237 clearMatched : function()
238 {
239 this._.isMatched = false;
240 },
241
242 isMatched : function()
243 {
244 return this._.isMatched;
245 },
246
247 /**
248 * Hightlight the current matched chunk of text.
249 */
250 highlight : function()
251 {
252 // Do not apply if nothing is found.
253 if ( this._.cursors.length < 1 )
254 return;
255
256 // Remove the previous highlight if there's one.
257 if ( this._.highlightRange )
258 this.removeHighlight();
259
260 // Apply the highlight.
261 var range = this.toDomRange(),
262 bookmark = range.createBookmark();
263 highlightStyle.applyToRange( range );
264 range.moveToBookmark( bookmark );
265 this._.highlightRange = range;
266
267 // Scroll the editor to the highlighted area.
268 var element = range.startContainer;
269 if ( element.type != CKEDITOR.NODE_ELEMENT )
270 element = element.getParent();
271 element.scrollIntoView();
272
273 // Update the character cursors.
274 this.updateFromDomRange( range );
275 },
276
277 /**
278 * Remove highlighted find result.
279 */
280 removeHighlight : function()
281 {
282 if ( !this._.highlightRange )
283 return;
284
285 var bookmark = this._.highlightRange.createBookmark();
286 highlightStyle.removeFromRange( this._.highlightRange );
287 this._.highlightRange.moveToBookmark( bookmark );
288 this.updateFromDomRange( this._.highlightRange );
289 this._.highlightRange = null;
290 },
291
292 isReadOnly : function()
293 {
294 if ( !this._.highlightRange )
295 return 0;
296
297 return this._.highlightRange.startContainer.isReadOnly();
298 },
299
300 moveBack : function()
301 {
302 var retval = this._.walker.back(),
303 cursors = this._.cursors;
304
305 if ( retval.hitMatchBoundary )
306 this._.cursors = cursors = [];
307
308 cursors.unshift( retval );
309 if ( cursors.length > this._.rangeLength )
310 cursors.pop();
311
312 return retval;
313 },
314
315 moveNext : function()
316 {
317 var retval = this._.walker.next(),
318 cursors = this._.cursors;
319
320 // Clear the cursors queue if we've crossed a match boundary.
321 if ( retval.hitMatchBoundary )
322 this._.cursors = cursors = [];
323
324 cursors.push( retval );
325 if ( cursors.length > this._.rangeLength )
326 cursors.shift();
327
328 return retval;
329 },
330
331 getEndCharacter : function()
332 {
333 var cursors = this._.cursors;
334 if ( cursors.length < 1 )
335 return null;
336
337 return cursors[ cursors.length - 1 ].character;
338 },
339
340 getNextCharacterRange : function( maxLength )
341 {
342 var lastCursor,
343 nextRangeWalker,
344 cursors = this._.cursors;
345
346 if ( ( lastCursor = cursors[ cursors.length - 1 ] ) && lastCursor.textNode )
347 nextRangeWalker = new characterWalker( getRangeAfterCursor( lastCursor ) );
348 // In case it's an empty range (no cursors), figure out next range from walker (#4951).
349 else
350 nextRangeWalker = this._.walker;
351
352 return new characterRange( nextRangeWalker, maxLength );
353 },
354
355 getCursors : function()
356 {
357 return this._.cursors;
358 }
359 };
360
361
362 // The remaining document range after the character cursor.
363 function getRangeAfterCursor( cursor , inclusive )
364 {
365 var range = new CKEDITOR.dom.range();
366 range.setStart( cursor.textNode,
367 ( inclusive ? cursor.offset : cursor.offset + 1 ) );
368 range.setEndAt( editor.document.getBody(),
369 CKEDITOR.POSITION_BEFORE_END );
370 return range;
371 }
372
373 // The document range before the character cursor.
374 function getRangeBeforeCursor( cursor )
375 {
376 var range = new CKEDITOR.dom.range();
377 range.setStartAt( editor.document.getBody(),
378 CKEDITOR.POSITION_AFTER_START );
379 range.setEnd( cursor.textNode, cursor.offset );
380 return range;
381 }
382
383 var KMP_NOMATCH = 0,
384 KMP_ADVANCED = 1,
385 KMP_MATCHED = 2;
386 /**
387 * Examination the occurrence of a word which implement KMP algorithm.
388 */
389 var kmpMatcher = function( pattern, ignoreCase )
390 {
391 var overlap = [ -1 ];
392 if ( ignoreCase )
393 pattern = pattern.toLowerCase();
394 for ( var i = 0 ; i < pattern.length ; i++ )
395 {
396 overlap.push( overlap[i] + 1 );
397 while ( overlap[ i + 1 ] > 0
398 && pattern.charAt( i ) != pattern
399 .charAt( overlap[ i + 1 ] - 1 ) )
400 overlap[ i + 1 ] = overlap[ overlap[ i + 1 ] - 1 ] + 1;
401 }
402
403 this._ = {
404 overlap : overlap,
405 state : 0,
406 ignoreCase : !!ignoreCase,
407 pattern : pattern
408 };
409 };
410
411 kmpMatcher.prototype =
412 {
413 feedCharacter : function( c )
414 {
415 if ( this._.ignoreCase )
416 c = c.toLowerCase();
417
418 while ( true )
419 {
420 if ( c == this._.pattern.charAt( this._.state ) )
421 {
422 this._.state++;
423 if ( this._.state == this._.pattern.length )
424 {
425 this._.state = 0;
426 return KMP_MATCHED;
427 }
428 return KMP_ADVANCED;
429 }
430 else if ( !this._.state )
431 return KMP_NOMATCH;
432 else
433 this._.state = this._.overlap[ this._.state ];
434 }
435
436 return null;
437 },
438
439 reset : function()
440 {
441 this._.state = 0;
442 }
443 };
444
445 var wordSeparatorRegex =
446 /[.,"'?!;: \u0085\u00a0\u1680\u280e\u2028\u2029\u202f\u205f\u3000]/;
447
448 var isWordSeparator = function( c )
449 {
450 if ( !c )
451 return true;
452 var code = c.charCodeAt( 0 );
453 return ( code >= 9 && code <= 0xd )
454 || ( code >= 0x2000 && code <= 0x200a )
455 || wordSeparatorRegex.test( c );
456 };
457
458 var finder = {
459 searchRange : null,
460 matchRange : null,
461 find : function( pattern, matchCase, matchWord, matchCyclic, highlightMatched, cyclicRerun )
462 {
463 if ( !this.matchRange )
464 this.matchRange =
465 new characterRange(
466 new characterWalker( this.searchRange ),
467 pattern.length );
468 else
469 {
470 this.matchRange.removeHighlight();
471 this.matchRange = this.matchRange.getNextCharacterRange( pattern.length );
472 }
473
474 var matcher = new kmpMatcher( pattern, !matchCase ),
475 matchState = KMP_NOMATCH,
476 character = '%';
477
478 while ( character !== null )
479 {
480 this.matchRange.moveNext();
481 while ( ( character = this.matchRange.getEndCharacter() ) )
482 {
483 matchState = matcher.feedCharacter( character );
484 if ( matchState == KMP_MATCHED )
485 break;
486 if ( this.matchRange.moveNext().hitMatchBoundary )
487 matcher.reset();
488 }
489
490 if ( matchState == KMP_MATCHED )
491 {
492 if ( matchWord )
493 {
494 var cursors = this.matchRange.getCursors(),
495 tail = cursors[ cursors.length - 1 ],
496 head = cursors[ 0 ];
497
498 var headWalker = new characterWalker( getRangeBeforeCursor( head ), true ),
499 tailWalker = new characterWalker( getRangeAfterCursor( tail ), true );
500
501 if ( ! ( isWordSeparator( headWalker.back().character )
502 && isWordSeparator( tailWalker.next().character ) ) )
503 continue;
504 }
505 this.matchRange.setMatched();
506 if ( highlightMatched !== false )
507 this.matchRange.highlight();
508 return true;
509 }
510 }
511
512 this.matchRange.clearMatched();
513 this.matchRange.removeHighlight();
514 // Clear current session and restart with the default search
515 // range.
516 // Re-run the finding once for cyclic.(#3517)
517 if ( matchCyclic && !cyclicRerun )
518 {
519 this.searchRange = getSearchRange( 1 );
520 this.matchRange = null;
521 return arguments.callee.apply( this,
522 Array.prototype.slice.call( arguments ).concat( [ true ] ) );
523 }
524
525 return false;
526 },
527
528 /**
529 * Record how much replacement occurred toward one replacing.
530 */
531 replaceCounter : 0,
532
533 replace : function( dialog, pattern, newString, matchCase, matchWord,
534 matchCyclic , isReplaceAll )
535 {
536 isReplace = 1;
537
538 // Successiveness of current replace/find.
539 var result = 0;
540
541 // 1. Perform the replace when there's already a match here.
542 // 2. Otherwise perform the find but don't replace it immediately.
543 if ( this.matchRange && this.matchRange.isMatched()
544 && !this.matchRange._.isReplaced && !this.matchRange.isReadOnly() )
545 {
546 // Turn off highlight for a while when saving snapshots.
547 this.matchRange.removeHighlight();
548 var domRange = this.matchRange.toDomRange();
549 var text = editor.document.createText( newString );
550 if ( !isReplaceAll )
551 {
552 // Save undo snaps before and after the replacement.
553 var selection = editor.getSelection();
554 selection.selectRanges( [ domRange ] );
555 editor.fire( 'saveSnapshot' );
556 }
557 domRange.deleteContents();
558 domRange.insertNode( text );
559 if ( !isReplaceAll )
560 {
561 selection.selectRanges( [ domRange ] );
562 editor.fire( 'saveSnapshot' );
563 }
564 this.matchRange.updateFromDomRange( domRange );
565 if ( !isReplaceAll )
566 this.matchRange.highlight();
567 this.matchRange._.isReplaced = true;
568 this.replaceCounter++;
569 result = 1;
570 }
571 else
572 result = this.find( pattern, matchCase, matchWord, matchCyclic, !isReplaceAll );
573
574 isReplace = 0;
575
576 return result;
577 }
578 };
579
580 /**
581 * The range in which find/replace happened, receive from user
582 * selection prior.
583 */
584 function getSearchRange( isDefault )
585 {
586 var searchRange,
587 sel = editor.getSelection(),
588 body = editor.document.getBody();
589 if ( sel && !isDefault )
590 {
591 searchRange = sel.getRanges()[ 0 ].clone();
592 searchRange.collapse( true );
593 }
594 else
595 {
596 searchRange = new CKEDITOR.dom.range();
597 searchRange.setStartAt( body, CKEDITOR.POSITION_AFTER_START );
598 }
599 searchRange.setEndAt( body, CKEDITOR.POSITION_BEFORE_END );
600 return searchRange;
601 }
602
603 var lang = editor.lang.findAndReplace;
604 return {
605 title : lang.title,
606 resizable : CKEDITOR.DIALOG_RESIZE_NONE,
607 minWidth : 350,
608 minHeight : 170,
609 buttons : [ CKEDITOR.dialog.cancelButton ], // Cancel button only.
610 contents : [
611 {
612 id : 'find',
613 label : lang.find,
614 title : lang.find,
615 accessKey : '',
616 elements : [
617 {
618 type : 'hbox',
619 widths : [ '230px', '90px' ],
620 children :
621 [
622 {
623 type : 'text',
624 id : 'txtFindFind',
625 label : lang.findWhat,
626 isChanged : false,
627 labelLayout : 'horizontal',
628 accessKey : 'F'
629 },
630 {
631 type : 'button',
632 id : 'btnFind',
633 align : 'left',
634 style : 'width:100%',
635 label : lang.find,
636 onClick : function()
637 {
638 var dialog = this.getDialog();
639 if ( !finder.find( dialog.getValueOf( 'find', 'txtFindFind' ),
640 dialog.getValueOf( 'find', 'txtFindCaseChk' ),
641 dialog.getValueOf( 'find', 'txtFindWordChk' ),
642 dialog.getValueOf( 'find', 'txtFindCyclic' ) ) )
643 alert( lang
644 .notFoundMsg );
645 }
646 }
647 ]
648 },
649 {
650 type : 'fieldset',
651 label : CKEDITOR.tools.htmlEncode( lang.findOptions ),
652 style : 'margin-top:29px',
653 children :
654 [
655 {
656 type : 'vbox',
657 padding : 0,
658 children :
659 [
660 {
661 type : 'checkbox',
662 id : 'txtFindCaseChk',
663 isChanged : false,
664 label : lang.matchCase
665 },
666 {
667 type : 'checkbox',
668 id : 'txtFindWordChk',
669 isChanged : false,
670 label : lang.matchWord
671 },
672 {
673 type : 'checkbox',
674 id : 'txtFindCyclic',
675 isChanged : false,
676 'default' : true,
677 label : lang.matchCyclic
678 }
679 ]
680 }
681 ]
682 }
683 ]
684 },
685 {
686 id : 'replace',
687 label : lang.replace,
688 accessKey : 'M',
689 elements : [
690 {
691 type : 'hbox',
692 widths : [ '230px', '90px' ],
693 children :
694 [
695 {
696 type : 'text',
697 id : 'txtFindReplace',
698 label : lang.findWhat,
699 isChanged : false,
700 labelLayout : 'horizontal',
701 accessKey : 'F'
702 },
703 {
704 type : 'button',
705 id : 'btnFindReplace',
706 align : 'left',
707 style : 'width:100%',
708 label : lang.replace,
709 onClick : function()
710 {
711 var dialog = this.getDialog();
712 if ( !finder.replace( dialog,
713 dialog.getValueOf( 'replace', 'txtFindReplace' ),
714 dialog.getValueOf( 'replace', 'txtReplace' ),
715 dialog.getValueOf( 'replace', 'txtReplaceCaseChk' ),
716 dialog.getValueOf( 'replace', 'txtReplaceWordChk' ),
717 dialog.getValueOf( 'replace', 'txtReplaceCyclic' ) ) )
718 alert( lang
719 .notFoundMsg );
720 }
721 }
722 ]
723 },
724 {
725 type : 'hbox',
726 widths : [ '230px', '90px' ],
727 children :
728 [
729 {
730 type : 'text',
731 id : 'txtReplace',
732 label : lang.replaceWith,
733 isChanged : false,
734 labelLayout : 'horizontal',
735 accessKey : 'R'
736 },
737 {
738 type : 'button',
739 id : 'btnReplaceAll',
740 align : 'left',
741 style : 'width:100%',
742 label : lang.replaceAll,
743 isChanged : false,
744 onClick : function()
745 {
746 var dialog = this.getDialog();
747 var replaceNums;
748
749 finder.replaceCounter = 0;
750
751 // Scope to full document.
752 finder.searchRange = getSearchRange( 1 );
753 if ( finder.matchRange )
754 {
755 finder.matchRange.removeHighlight();
756 finder.matchRange = null;
757 }
758 editor.fire( 'saveSnapshot' );
759 while ( finder.replace( dialog,
760 dialog.getValueOf( 'replace', 'txtFindReplace' ),
761 dialog.getValueOf( 'replace', 'txtReplace' ),
762 dialog.getValueOf( 'replace', 'txtReplaceCaseChk' ),
763 dialog.getValueOf( 'replace', 'txtReplaceWordChk' ),
764 false, true ) )
765 { /*jsl:pass*/ }
766
767 if ( finder.replaceCounter )
768 {
769 alert( lang.replaceSuccessMsg.replace( /%1/, finder.replaceCounter ) );
770 editor.fire( 'saveSnapshot' );
771 }
772 else
773 alert( lang.notFoundMsg );
774 }
775 }
776 ]
777 },
778 {
779 type : 'fieldset',
780 label : CKEDITOR.tools.htmlEncode( lang.findOptions ),
781 children :
782 [
783 {
784 type : 'vbox',
785 padding : 0,
786 children :
787 [
788 {
789 type : 'checkbox',
790 id : 'txtReplaceCaseChk',
791 isChanged : false,
792 label : lang.matchCase
793 },
794 {
795 type : 'checkbox',
796 id : 'txtReplaceWordChk',
797 isChanged : false,
798 label : lang.matchWord
799 },
800 {
801 type : 'checkbox',
802 id : 'txtReplaceCyclic',
803 isChanged : false,
804 'default' : true,
805 label : lang.matchCyclic
806 }
807 ]
808 }
809 ]
810 }
811 ]
812 }
813 ],
814 onLoad : function()
815 {
816 var dialog = this;
817
818 // Keep track of the current pattern field in use.
819 var patternField, wholeWordChkField;
820
821 // Ignore initial page select on dialog show
822 var isUserSelect = 0;
823 this.on( 'hide', function()
824 {
825 isUserSelect = 0;
826 });
827 this.on( 'show', function()
828 {
829 isUserSelect = 1;
830 });
831
832 this.selectPage = CKEDITOR.tools.override( this.selectPage, function( originalFunc )
833 {
834 return function( pageId )
835 {
836 originalFunc.call( dialog, pageId );
837
838 var currPage = dialog._.tabs[ pageId ];
839 var patternFieldInput, patternFieldId, wholeWordChkFieldId;
840 patternFieldId = pageId === 'find' ? 'txtFindFind' : 'txtFindReplace';
841 wholeWordChkFieldId = pageId === 'find' ? 'txtFindWordChk' : 'txtReplaceWordChk';
842
843 patternField = dialog.getContentElement( pageId,
844 patternFieldId );
845 wholeWordChkField = dialog.getContentElement( pageId,
846 wholeWordChkFieldId );
847
848 // Prepare for check pattern text filed 'keyup' event
849 if ( !currPage.initialized )
850 {
851 patternFieldInput = CKEDITOR.document
852 .getById( patternField._.inputId );
853 currPage.initialized = true;
854 }
855
856 // Synchronize fields on tab switch.
857 if ( isUserSelect )
858 syncFieldsBetweenTabs.call( this, pageId );
859 };
860 } );
861
862 },
863 onShow : function()
864 {
865 // Establish initial searching start position.
866 finder.searchRange = getSearchRange();
867
868 // Fill in the find field with selected text.
869 var selectedText = this.getParentEditor().getSelection().getSelectedText(),
870 patternFieldId = ( startupPage == 'find' ? 'txtFindFind' : 'txtFindReplace' );
871
872 var field = this.getContentElement( startupPage, patternFieldId );
873 field.setValue( selectedText );
874 field.select();
875
876 this.selectPage( startupPage );
877
878 this[ ( startupPage == 'find' && this._.editor.readOnly? 'hide' : 'show' ) + 'Page' ]( 'replace');
879 },
880 onHide : function()
881 {
882 var range;
883 if ( finder.matchRange && finder.matchRange.isMatched() )
884 {
885 finder.matchRange.removeHighlight();
886 editor.focus();
887
888 range = finder.matchRange.toDomRange();
889 if ( range )
890 editor.getSelection().selectRanges( [ range ] );
891 }
892
893 // Clear current session before dialog close
894 delete finder.matchRange;
895 },
896 onFocus : function()
897 {
898 if ( startupPage == 'replace' )
899 return this.getContentElement( 'replace', 'txtFindReplace' );
900 else
901 return this.getContentElement( 'find', 'txtFindFind' );
902 }
903 };
904 };
905
906 CKEDITOR.dialog.add( 'find', function( editor )
907 {
908 return findDialog( editor, 'find' );
909 });
910
911 CKEDITOR.dialog.add( 'replace', function( editor )
912 {
913 return findDialog( editor, 'replace' );
914 });
915})();
Note: See TracBrowser for help on using the repository browser.