/*
Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
Available via Academic Free License >= 2.1 OR the modified BSD license.
see: http://dojotoolkit.org/license for details
*/
if(!dojo._hasResource["dojox.editor.plugins.FindReplace"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["dojox.editor.plugins.FindReplace"] = true;
dojo.provide("dojox.editor.plugins.FindReplace");
dojo.require("dojo.string");
dojo.require("dijit.TooltipDialog");
dojo.require("dijit.Toolbar");
dojo.require("dijit.form.CheckBox");
dojo.require("dijit.form.TextBox");
dojo.require("dijit._editor._Plugin");
dojo.require("dijit.form.Button");
dojo.require("dojox.editor.plugins.ToolbarLineBreak");
dojo.require("dojo.i18n");
dojo.requireLocalization("dojox.editor.plugins", "FindReplace", null, "ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,kk,ko,nb,nl,pl,pt,pt-pt,ro,ru,sk,sl,sv,th,tr,zh,zh-tw");
dojo.experimental("dojox.editor.plugins.FindReplace");
dojo.declare("dojox.editor.plugins._FindReplaceCloseBox", [dijit._Widget, dijit._Templated], {
// summary:
// Base class for widgets that contains a button labeled X
// to close the tool bar.
btnId: "",
widget: null,
widgetsInTemplate: true,
templateString:
"<span style='float: right' class='dijitInline' tabindex='-1'>" +
"<button class='dijit dijitReset dijitInline' " +
"id='${btnId}' dojoAttachPoint='button' dojoType='dijit.form.Button' tabindex='-1' iconClass='dijitEditorIconsFindReplaceClose' showLabel='false'>X</button>" +
"</span>",
postMixInProperties: function(){
// Set some substitution variables used in the template
this.id = dijit.getUniqueId(this.declaredClass.replace(/\./g,"_"));
this.btnId = this.id + "_close";
this.inherited(arguments);
},
startup: function(){
this.connect(this.button, "onClick", "onClick");
},
onClick: function(){
}
});
dojo.declare("dojox.editor.plugins._FindReplaceTextBox",
[dijit._Widget, dijit._Templated],{
// summary:
// Base class for widgets that contains a label (like "Font:")
// and a TextBox to pick a value.
// Used as Toolbar entry.
// textId: [public] String
// The id of the enhanced textbox
textId: "",
// label: [public] String
// The label of the enhanced textbox
label: "",
// tooltip: [public] String
// The tooltip of the enhanced textbox when the mouse is hovering on it
toolTip: "",
widget: null,
widgetsInTemplate: true,
templateString:
"<span style='white-space: nowrap' class='dijit dijitReset dijitInline dijitEditorFindReplaceTextBox' " +
"title='${tooltip}' tabindex='-1'>" +
"<label class='dijitLeft dijitInline' for='${textId}' tabindex='-1'>${label}</label>" +
"<input dojoType='dijit.form.TextBox' required='false' intermediateChanges='true' class='focusTextBox'" +
"tabIndex='0' id='${textId}' dojoAttachPoint='textBox, focusNode' value='' dojoAttachEvent='onKeyPress: _onKeyPress'/>" +
"</span>",
postMixInProperties: function(){
// Set some substitution variables used in the template
this.id = dijit.getUniqueId(this.declaredClass.replace(/\./g,"_"));
this.textId = this.id + "_text";
this.inherited(arguments);
},
postCreate: function(){
this.textBox.set("value", "");
this.disabled = this.textBox.get("disabled");
this.connect(this.textBox, "onChange", "onChange");
},
_setValueAttr: function(/*String*/ value){
//If the value is not a permitted value, just set empty string to prevent showing the warning icon
this.value = value;
this.textBox.set("value", value);
},
focus: function(){
this.textBox.focus();
},
_setDisabledAttr: function(/*Boolean*/ value){
// summary:
// Over-ride for the textbox's 'disabled' attribute so that it can be
// disabled programmatically.
// value:
// The boolean value to indicate if the textbox should be disabled or not
// tags:
// private
this.disabled = value;
this.textBox.set("disabled", value);
},
onChange: function(/*String*/ val){
// summary:
// Stub function for change events on the box.
// tags:
// public
this.value= val;
},
_onKeyPress: function(/*Event*/ evt){
// summary:
// Handle the arrow key events
// evt:
// Event object passed to this handler
// tags:
// private
var start = 0;
var end = 0;
// If CTRL, ALT or SHIFT is not held on
if(evt.target && !evt.ctrlKey && !evt.altKey && !evt.shiftKey){
if(evt.keyCode == dojo.keys.LEFT_ARROW){
start = evt.target.selectionStart;
end = evt.target.selectionEnd;
if(start < end){
dijit.selectInputText(evt.target, start, start);
dojo.stopEvent(evt);
}
}else if(evt.keyCode == dojo.keys.RIGHT_ARROW){
start = evt.target.selectionStart;
end = evt.target.selectionEnd;
if(start < end){
dijit.selectInputText(evt.target, end, end);
dojo.stopEvent(evt);
}
}
}
}
});
dojo.declare("dojox.editor.plugins._FindReplaceCheckBox",
[dijit._Widget, dijit._Templated],{
// summary:
// Base class for widgets that contains a label (like "Match case: ")
// and a checkbox to indicate if it is checked or not.
// Used as Toolbar entry.
// checkId: [public] String
// The id of the enhanced checkbox
checkId: "",
// label: [public] String
// The label of the enhanced checkbox
label: "",
// tooltip: [public] String
// The tooltip of the enhanced checkbox when the mouse is hovering it
tooltip: "",
widget: null,
widgetsInTemplate: true,
templateString:
"<span style='white-space: nowrap' tabindex='-1' " +
"class='dijit dijitReset dijitInline dijitEditorFindReplaceCheckBox' title='${tooltip}' >" +
"<input dojoType='dijit.form.CheckBox' required=false " +
"tabIndex='0' id='${checkId}' dojoAttachPoint='checkBox, focusNode' value=''/>" +
"<label tabindex='-1' class='dijitLeft dijitInline' for='${checkId}'>${label}</label>" +
"</span>",
postMixInProperties: function(){
// Set some substitution variables used in the template
this.id = dijit.getUniqueId(this.declaredClass.replace(/\./g,"_"));
this.checkId = this.id + "_check";
this.inherited(arguments);
},
postCreate: function(){
this.checkBox.set("checked", false);
this.disabled = this.checkBox.get("disabled");
this.checkBox.isFocusable = function(){ return false; };
},
_setValueAttr: function(/*Boolean*/ value){
// summary:
// Passthrough for checkbox.
// tags:
// private
this.checkBox.set('value', value);
},
_getValueAttr: function(){
// summary:
// Passthrough for checkbox.
// tags:
// private
return this.checkBox.get('value');
},
focus: function(){
// summary:
// Handle the focus event when this widget gets focused
// tags:
// private
this.checkBox.focus();
},
_setDisabledAttr: function(/*Boolean*/ value){
// summary:
// Over-ride for the button's 'disabled' attribute so that it can be
// disabled programmatically.
// value:
// The flag that indicates if the checkbox is disabled or not.
// tags:
// private
this.disabled = value;
this.checkBox.set("disabled", value);
}
});
dojo.declare("dojox.editor.plugins._FindReplaceToolbar", dijit.Toolbar, {
// summary:
// A toolbar that derived from dijit.Toolbar, which
// eliminates some unnecessary event response such as LEFT_ARROW pressing
// and click bubbling.
postCreate: function(){
this.connectKeyNavHandlers([], []); // Prevent arrow key navigation
this.connect(this.containerNode, "onclick", "_onToolbarEvent");
this.connect(this.containerNode, "onkeydown", "_onToolbarEvent");
dojo.addClass(this.domNode, "dijitToolbar");
},
addChild: function(/*dijit._Widget*/ widget, /*int?*/ insertIndex){
// summary:
// Add a child to our _Container and prevent the default
// arrow key navigation function. This function may bring in
// side effect
dijit._KeyNavContainer.superclass.addChild.apply(this, arguments);
},
_onToolbarEvent: function(/*Event*/ evt){
// Editor may have special treatment to some events, so stop the bubbling.
// evt:
// The Event object
// tages:
// private
evt.stopPropagation();
}
});
dojo.declare("dojox.editor.plugins.FindReplace",[dijit._editor._Plugin],{
// summary:
// This plugin provides a Find/Replace cabability for the editor.
// Note that this plugin is NOT supported on Opera currently, as opera
// does not implement a window.find or equiv function.
// buttonClass: [protected]
// Define the class of button the editor uses.
buttonClass: dijit.form.ToggleButton,
// iconClassPrefix: [const] String
// The CSS class name for the button node is formed from `iconClassPrefix` and `command`
iconClassPrefix: "dijitEditorIconsFindReplace",
// editor: [protected]
// The editor this plugin belongs to
editor: null,
// button: [protected]
// The toggle button
button: null,
// _frToolbar: [private]
// The toolbar that contain all the entries and buttons
_frToolbar: null,
// _closeBox: [private]
// The close button of the F/R toolbar
_closeBox: null,
// _findField: [private]
// The Find field of the F/R toolbar
_findField: null,
// _replaceField: [private]
// The Replace field of the F/R toolbar
_replaceField: null,
// _findButton: [private]
// The Find button of the F/R toolbar
_findButton: null,
// _replaceButton: [private]
// The Replace button of the F/R toolbar
_replaceButton: null,
// _replaceAllButton: [private]
// The ReplaceAll button of the F/R toolbar
_replaceAllButton: null,
// _caseSensitive: [private]
// The case sensitive checkbox
_caseSensitive: null,
// _backwards: [private]
// The backwards checkbox
_backwards: null,
// _promDialog: [private]
// The prompt message box that shows the user some messages
// such as the end of a search, the end of a replacement, etc.
_promDialog: null,
_promDialogTimeout: null,
// _strings: [private]
// The array that contains globalized strings
_strings: null,
_initButton: function(){
// summary:
// Over-ride for creation of the resize button.
this._strings = dojo.i18n.getLocalization("dojox.editor.plugins", "FindReplace");
this.button = new dijit.form.ToggleButton({
label: this._strings["findReplace"],
showLabel: false,
iconClass: this.iconClassPrefix + " dijitEditorIconFindString",
tabIndex: "-1",
onChange: dojo.hitch(this, "_toggleFindReplace")
});
if(dojo.isOpera){
// Not currently supported on Opera!
this.button.set("disabled", true);
}
//Link up so that if the toggle is disabled, then the view of Find/Replace is closed.
this.connect(this.button, "set", dojo.hitch(this, function(attr, val){
if(attr === "disabled"){
this._toggleFindReplace((!val && this._displayed), true, true);
}
}));
},
setEditor: function(editor){
// summary:
// This is a callback handler that set a reference to the editor this plugin
// hosts in
this.editor = editor;
this._initButton();
},
toggle: function(){
// summary:
// Function to allow programmatic toggling of the find toolbar.
// tags:
// public
this.button.set("checked", !this.button.get("checked"));
},
_toggleFindReplace: function(/*Boolean*/ show, /*Boolean?*/ ignoreState, /*Boolean?*/ buttonDisabled){
// summary:
// Function to toggle whether or not find/replace is displayed.
// show:
// Indicate if the toolbar is shown or not
// ignoreState:
// Indicate if the status should be ignored or not
// blurEditor:
// Indicate if the focus should be removed from the editor or not
// tags:
// private
var size = dojo.marginBox(this.editor.domNode);
if(show && !dojo.isOpera){
dojo.style(this._frToolbar.domNode, "display", "block");
// Auto populate the Find field
this._populateFindField();
if(!ignoreState){
this._displayed = true;
}
}else{
dojo.style(this._frToolbar.domNode, "display", "none");
if(!ignoreState){
this._displayed = false;
}
// If the toggle button is disabled, it is most likely that
// another plugin such as ViewSource disables it.
// So we do not need to focus the text area of the editor to
// prevent the editor from an invalid status.
// Please refer to dijit._editor.plugins.ViewSource for more details.
if(!buttonDisabled){
this.editor.focus();
}
}
// Resize the editor.
this.editor.resize({h: size.h});
},
_populateFindField: function(){
// summary:
// Populate the Find field with selected text when dialog initially displayed.
// Auto-select text in Find field after it is populated.
// If nothing selected, restore previous entry from the same session.
// tags:
// private
var ed = this.editor;
var win = ed.window;
var selectedTxt = dojo.withGlobal(ed.window, "getSelectedText", dijit._editor.selection, [null]);
if(this._findField && this._findField.textBox){
if(selectedTxt){
this._findField.textBox.set("value", selectedTxt);
}
this._findField.textBox.focus();
dijit.selectInputText(this._findField.textBox.focusNode);
}
},
setToolbar: function(/*dijit.Toolbar*/ toolbar){
// summary:
// Over-ride so that find/replace toolbar is appended after the current toolbar.
// toolbar:
// The current toolbar of the editor
// tags:
// public
this.inherited(arguments);
if(!dojo.isOpera){
var _tb = this._frToolbar = new dojox.editor.plugins._FindReplaceToolbar();
dojo.style(_tb.domNode, "display", "none");
dojo.place(_tb.domNode, toolbar.domNode, "after");
_tb.startup();
// IE6 will put the close box in a new line when its style is "float: right".
// So place the close box ahead of the other fields, which makes it align with
// the other components.
this._closeBox = new dojox.editor.plugins._FindReplaceCloseBox();
_tb.addChild(this._closeBox);
// Define the search/replace fields.
this._findField = new dojox.editor.plugins._FindReplaceTextBox(
{label: this._strings["findLabel"], tooltip: this._strings["findTooltip"]});
_tb.addChild(this._findField);
this._replaceField = new dojox.editor.plugins._FindReplaceTextBox(
{label: this._strings["replaceLabel"], tooltip: this._strings["replaceTooltip"]});
_tb.addChild(this._replaceField);
// Define the Find/Replace/ReplaceAll buttons.
_tb.addChild(new dojox.editor.plugins.ToolbarLineBreak());
this._findButton = new dijit.form.Button({label: this._strings["findButton"], showLabel: true,
iconClass: this.iconClassPrefix + " dijitEditorIconFind"});
this._findButton.titleNode.title = this._strings["findButtonTooltip"];
_tb.addChild(this._findButton);
this._replaceButton = new dijit.form.Button({label: this._strings["replaceButton"], showLabel: true,
iconClass: this.iconClassPrefix + " dijitEditorIconReplace"});
this._replaceButton.titleNode.title = this._strings["replaceButtonTooltip"];
_tb.addChild(this._replaceButton);
this._replaceAllButton = new dijit.form.Button({label: this._strings["replaceAllButton"], showLabel: true,
iconClass: this.iconClassPrefix + " dijitEditorIconReplaceAll"});
this._replaceAllButton.titleNode.title = this._strings["replaceAllButtonTooltip"];
_tb.addChild(this._replaceAllButton);
// Define the option checkboxes.
this._caseSensitive = new dojox.editor.plugins._FindReplaceCheckBox(
{label: this._strings["matchCase"], tooltip: this._strings["matchCaseTooltip"]});
_tb.addChild(this._caseSensitive);
this._backwards = new dojox.editor.plugins._FindReplaceCheckBox(
{label: this._strings["backwards"], tooltip: this._strings["backwardsTooltip"]});
_tb.addChild(this._backwards);
// Set initial states, buttons should be disabled unless content is
// present in the fields.
this._findButton.set("disabled", true);
this._replaceButton.set("disabled", true);
this._replaceAllButton.set("disabled", true);
// Connect the event to the status of the items
this.connect(this._findField, "onChange", "_checkButtons");
this.connect(this._findField, "onKeyDown", "_onFindKeyDown");
this.connect(this._replaceField, "onKeyDown", "_onReplaceKeyDown");
// Connect up the actual search events.
this.connect(this._findButton, "onClick", "_find");
this.connect(this._replaceButton, "onClick", "_replace");
this.connect(this._replaceAllButton, "onClick", "_replaceAll");
// Connect up the close event
this.connect(this._closeBox, "onClick", "toggle");
// Prompt for the message
this._promDialog = new dijit.TooltipDialog();
this._promDialog.startup();
this._promDialog.set("content", "");
}
},
_checkButtons: function(){
// summary:
// Ensure that all the buttons are in a correct status
// when certain events are fired.
var fText = this._findField.get("value");
if(fText){
// Only enable if find text is not empty or just blank/spaces.
this._findButton.set("disabled", false);
this._replaceButton.set("disabled", false);
this._replaceAllButton.set("disabled", false);
}else{
this._findButton.set("disabled", true);
this._replaceButton.set("disabled", true);
this._replaceAllButton.set("disabled", true);
}
},
_onFindKeyDown: function(evt){
if(evt.keyCode == dojo.keys.ENTER){
// Perform the default search action
this._find();
dojo.stopEvent(evt);
}
},
_onReplaceKeyDown: function(evt){
if(evt.keyCode == dojo.keys.ENTER){
// Perform the default replace action
if(!this._replace()) this._replace();
dojo.stopEvent(evt);
}
},
_find: function(/*Boolean?*/ showMessage){
// summary:
// This function invokes a find on the editor document with the noted options for
// find.
// showMessage:
// Indicated whether the tooltip is shown or not when the search reaches the end
// tags:
// private.
// returns:
// Boolean indicating if the content was found or not.
var txt = this._findField.get("value") || "";
if(txt){
var caseSensitive = this._caseSensitive.get("value");
var backwards = this._backwards.get("value");
var isFound = this._findText(txt, caseSensitive, backwards);
if(!isFound && showMessage){
this._promDialog.set("content", dojo.string.substitute(
this._strings["eofDialogText"], {"0": this._strings["eofDialogTextFind"]}));
dijit.popup.open({popup: this._promDialog, around: this._findButton.domNode});
this._promDialogTimeout = setTimeout(dojo.hitch(this, function(){
clearTimeout(this._promDialogTimeout);
this._promDialogTimeout = null;
dijit.popup.close(this._promDialog);
}), 3000);
setTimeout(dojo.hitch(this, function(){
this.editor.focus();
}), 0);
}
return isFound;
}
return false;
},
_replace: function(/*Boolean?*/ showMessage){
// summary:
// This function invokes a replace on the editor document with the noted options for replace
// showMessage:
// Indicate if the prompt message is shown or not when the replacement
// reaches the end
// tags:
// private
// returns:
// Boolean indicating if the content was replaced or not.
var isReplaced = false;
var ed = this.editor;
ed.focus();
var txt = this._findField.get("value") || "";
var repTxt = this._replaceField.get("value") || "";
if(txt){
var caseSensitive = this._caseSensitive.get("value");
// Check if it is forced to be forwards or backwards
var backwards = this._backwards.get("value");
//Replace the current selected text if it matches the pattern
var selected = dojo.withGlobal(ed.window, "getSelectedText", dijit._editor.selection, [null]);
// Handle checking/replacing current selection. For some reason on Moz
// leading whitespace is trimmed, so we have to trim it down on this check
// or we don't always replace. Moz bug!
if(dojo.isMoz){
txt = dojo.trim(txt);
selected = dojo.trim(selected);
}
var regExp = this._filterRegexp(txt, !caseSensitive);
if(selected && regExp.test(selected)){
ed.execCommand("inserthtml", repTxt);
isReplaced = true;
if(backwards){
// Move to the beginning of the replaced text
// to avoid the infinite recursive replace
this._findText(repTxt, caseSensitive, backwards);
dojo.withGlobal(ed.window, "collapse", dijit._editor.selection, [true]);
}
}
if(!this._find(false) && showMessage){ // Find the next
this._promDialog.set("content", dojo.string.substitute(
this._strings["eofDialogText"], {"0": this._strings["eofDialogTextReplace"]}));
dijit.popup.open({popup: this._promDialog, around: this._replaceButton.domNode});
this._promDialogTimeout = setTimeout(dojo.hitch(this, function(){
clearTimeout(this._promDialogTimeout);
this._promDialogTimeout = null;
dijit.popup.close(this._promDialog);
}), 3000);
setTimeout(dojo.hitch(this, function(){
this.editor.focus();
}), 0);
}
return isReplaced;
}
return null;
},
_replaceAll: function(/*Boolean?*/ showMessage){
// summary:
// This function replaces all the matched content on the editor document
// with the noted options for replace
// showMessage:
// Indicate if the prompt message is shown or not when the action is done.
// tags:
// private
var replaced = 0;
var backwards = this._backwards.get("value");
if(backwards){
this.editor.placeCursorAtEnd();
}else{
this.editor.placeCursorAtStart();
}
// The _replace will return false if the current selection deos not match
// the searched text. So try the first attempt so that the selection
// is always the searched text if there is one that matches
if(this._replace(false)) { replaced++; }
// Do the replace via timeouts to avoid locking the browser up for a lot of replaces.
var loopBody = dojo.hitch(this, function(){
if(this._replace(false)){
replaced++;
setTimeout(loopBody, 10);
}else{
if(showMessage){
this._promDialog.set("content", dojo.string.substitute(
this._strings["replaceDialogText"], {"0": "" + replaced}));
dijit.popup.open({
popup: this._promDialog,
around: this._replaceAllButton.domNode
});
this._promDialogTimeout = setTimeout(dojo.hitch(this, function(){
clearTimeout(this._promDialogTimeout);
this._promDialogTimeout = null;
dijit.popup.close(this._promDialog);
}), 3000);
setTimeout(dojo.hitch(this, function(){
this._findField.focus();
this._findField.textBox.focusNode.select();
}), 0);
}
}
});
loopBody();
},
_findText: function(/*String*/ txt, /*Boolean*/ caseSensitive, /*Boolean*/ backwards){
// summary:
// This function invokes a find with specific options
// txt: String
// The text to locate in the document.
// caseSensitive: Boolean
// Whether or ot to search case-sensitively.
// backwards: Boolean
// Whether or not to search backwards in the document.
// tags:
// private.
// returns:
// Boolean indicating if the content was found or not.
var ed = this.editor;
var win = ed.window;
var found = false;
if(txt){
if(win.find){
found = win.find(txt, caseSensitive, backwards, false, false, false, false);
}else{
var doc = ed.document;
if(doc.selection){
/* IE */
// Focus to restore position/selection,
// then shift to search from current position.
this.editor.focus();
var txtRg = doc.body.createTextRange();
var curPos = doc.selection?doc.selection.createRange():null;
if(curPos){
if(backwards){
txtRg.setEndPoint("EndToStart", curPos);
}else{
txtRg.setEndPoint("StartToEnd", curPos);
}
}
var flags = caseSensitive?4:0;
if(backwards){
flags = flags | 1;
}
//flags = flags |
found = txtRg.findText(txt,txtRg.text.length,flags);
if(found){
txtRg.select();
}
}
}
}
return found;
},
_filterRegexp: function(/*String*/ pattern, /*Boolean*/ ignoreCase){
// summary:
// Helper function to convert a simple pattern to a regular expression for matching.
// description:
// Returns a regular expression object that conforms to the defined conversion rules.
// For example:
// ca* -> /^ca.*$/
// *ca* -> /^.*ca.*$/
// *c\*a* -> /^.*c\*a.*$/
// *c\*a?* -> /^.*c\*a..*$/
// and so on.
//
// pattern: string
// A simple matching pattern to convert that follows basic rules:
// * Means match anything, so ca* means match anything starting with ca
// ? Means match single character. So, b?b will match to bob and bab, and so on.
// \ is an escape character. So for example, \* means do not treat * as a match, but literal character *.
// To use a \ as a character in the string, it must be escaped. So in the pattern it should be
// represented by \\ to be treated as an ordinary \ character instead of an escape.
//
// ignoreCase:
// An optional flag to indicate if the pattern matching should be treated as case-sensitive or not when comparing
// By default, it is assumed case sensitive.
// tags:
// private
var rxp = "";
var c = null;
for(var i = 0; i < pattern.length; i++){
c = pattern.charAt(i);
switch(c){
case '\\':
rxp += c;
i++;
rxp += pattern.charAt(i);
break;
case '$':
case '^':
case '/':
case '+':
case '.':
case '|':
case '(':
case ')':
case '{':
case '}':
case '[':
case ']':
rxp += "\\"; //fallthrough
default:
rxp += c;
}
}
rxp = "^" + rxp + "$";
if(ignoreCase){
return new RegExp(rxp,"mi"); //RegExp
}else{
return new RegExp(rxp,"m"); //RegExp
}
},
updateState: function(){
// summary:
// Over-ride for button state control for disabled to work.
this.button.set("disabled", this.get("disabled"));
},
destroy: function(){
// summary:
// Cleanup of our custom toolbar.
this.inherited(arguments);
if(this._promDialogTimeout){
clearTimeout(this._promDialogTimeout);
this._promDialogTimeout = null;
dijit.popup.close(this._promDialog);
}
if(this._frToolbar){
this._frToolbar.destroyRecursive();
this._frToolbar = null;
}
if(this._promDialog){
this._promDialog.destroyRecursive();
this._promDialog = null;
}
}
});
// Register this plugin.
dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){
if(o.plugin){ return; }
var name = o.args.name.toLowerCase();
if(name === "findreplace"){
o.plugin = new dojox.editor.plugins.FindReplace({});
}
});
}