Added feature #13785: htmlArea RTE: Extjize Find & Replace dialogue
authorStanislas Rolland <typo3@sjbr.ca>
Wed, 10 Mar 2010 03:41:56 +0000 (03:41 +0000)
committerStanislas Rolland <typo3@sjbr.ca>
Wed, 10 Mar 2010 03:41:56 +0000 (03:41 +0000)
git-svn-id: https://svn.typo3.org/TYPO3v4/Core/trunk@7092 709f56b5-9817-0410-a4d7-c38de5d9e867

ChangeLog
typo3/sysext/rtehtmlarea/ChangeLog
typo3/sysext/rtehtmlarea/htmlarea/plugins/FindReplace/find-replace.js
typo3/sysext/rtehtmlarea/htmlarea/plugins/FindReplace/fr_engine.js [deleted file]
typo3/sysext/rtehtmlarea/htmlarea/plugins/FindReplace/locallang.xml
typo3/sysext/rtehtmlarea/htmlarea/plugins/FindReplace/popups/find_replace.html [deleted file]
typo3/sysext/rtehtmlarea/htmlarea/plugins/UndoRedo/undo-redo.js
typo3/sysext/rtehtmlarea/htmlarea/skins/default/htmlarea.css
typo3/sysext/t3skin/rtehtmlarea/htmlarea.css

index 7754c79..b558f47 100755 (executable)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2010-03-09  Stanislas Rolland  <typo3@sjbr.ca>
+
+       * Added feature #13785: htmlArea RTE: Extjize Find & Replace dialogue
+
 2010-03-08  Xavier Perseguers  <typo3@perseguers.ch>
 
        * Fixed bug #13766: Auto-increment does not work with driver odbc_mssql [adodb]
index 5b36a4e..77cc8ef 100644 (file)
@@ -1,3 +1,7 @@
+2010-03-09  Stanislas Rolland  <typo3@sjbr.ca>
+
+       * Added feature #13785: htmlArea RTE: Extjize Find & Replace dialogue
+
 2010-03-05  Stanislas Rolland  <typo3@sjbr.ca>
 
        * Follow-up to #13668: htmlArea RTE: Cleanup some unused code (statusbar)
index 54680d4..d4e976f 100644 (file)
  * TYPO3 SVN ID: $Id$
  */
 FindReplace = HTMLArea.Plugin.extend({
-
-       constructor : function(editor, pluginName) {
+       constructor: function(editor, pluginName) {
                this.base(editor, pluginName);
        },
-
        /*
         * This function gets called by the class constructor
         */
-       configurePlugin : function(editor) {
-
+       configurePlugin: function(editor) {
                /*
                 * Registering plugin "About" information
                 */
                var pluginInformation = {
-                       version         : "1.2",
-                       developer       : "Cau Guanabara & Stanislas Rolland",
-                       developerUrl    : "mailto:caugb@ibest.com.br",
-                       copyrightOwner  : "Cau Guanabara & Stanislas Rolland",
-                       sponsor         : "Independent production & SJBR",
-                       sponsorUrl      : "http://www.netflash.com.br/gb/HA3-rc1/examples/find-replace.html",
-                       license         : "GPL"
+                       version         : '2.0',
+                       developer       : 'Cau Guanabara & Stanislas Rolland',
+                       developerUrl    : 'http://www.sjbr.ca',
+                       copyrightOwner  : 'Cau Guanabara & Stanislas Rolland',
+                       sponsor         : 'Independent production & SJBR',
+                       sponsorUrl      : 'http://www.sjbr.ca',
+                       license         : 'GPL'
                };
                this.registerPluginInformation(pluginInformation);
-
                /*
                 * Registering the button
                 */
-               var buttonId = "FindReplace";
+               var buttonId = 'FindReplace';
                var buttonConfiguration = {
                        id              : buttonId,
-                       tooltip         : this.localize("Find and Replace"),
-                       action          : "onButtonPress",
+                       tooltip         : this.localize('Find and Replace'),
+                       action          : 'onButtonPress',
                        dialog          : true
                };
                this.registerButton(buttonConfiguration);
-
-               this.popupWidth = 400;
-               this.popupHeight = 360;
-
+                       // Compile regular expression to clean up marks
+               this.marksCleaningRE = /(<span\s+[^>]*id="?htmlarea-frmark[^>]*"?>)([^<>]*)(<\/span>)/gi;
                return true;
        },
-
        /*
-        * This function gets called when the button was pressed.
+        * This function gets called when the 'Find & Replace' button is pressed.
         *
         * @param       object          editor: the editor instance
         * @param       string          id: the button id or the key
         *
         * @return      boolean         false if action is completed
         */
-       onButtonPress : function (editor, id, target) {
+       onButtonPress: function (editor, id, target) {
                        // Could be a button or its hotkey
                var buttonId = this.translateHotKey(id);
                buttonId = buttonId ? buttonId : id;
-
-               var sel = this.editor.getSelectedHTML(), param = null;
-               if (/\w/.test(sel)) {
-                       sel = sel.replace(/<[^>]*>/g,"");
-                       sel = sel.replace(/&nbsp;/g,"");
+                       // Initialize search variables
+               this.buffer = null;
+               this.initVariables();
+                       // Disable the toolbar undo/redo buttons and snapshots while this window is opened
+               var plugin = this.getPluginInstance('UndoRedo');
+               if (plugin) {
+                       plugin.stop();
+                       var undo = this.getButton('Undo');
+                       if (undo) {
+                               undo.setDisabled(true);
+                       }
+                       var redo = this.getButton('Redo');
+                       if (redo) {
+                               redo.setDisabled(true);
+                       }
                }
-               if (/\w/.test(sel)) {
-                       param = { fr_pattern: sel };
+                       // Open dialogue window
+               this.openDialogue(
+                       buttonId,
+                       'Find and Replace',
+                       this.getWindowDimensions(
+                               {
+                                       width: 460,
+                                       height:360
+                               },
+                               buttonId
+                       )
+               );
+               return false;
+       },
+       /*
+        * Open the dialogue window
+        *
+        * @param       string          buttonId: the button id
+        * @param       string          title: the window title
+        * @param       integer         dimensions: the opening width of the window
+        *
+        * @return      void
+        */
+       openDialogue: function (buttonId, title, dimensions) {
+               this.dialog = new Ext.Window({
+                       title: this.localize(title),
+                       cls: 'htmlarea-window',
+                       border: false,
+                       width: dimensions.width,
+                       height: 'auto',
+                               // As of ExtJS 3.1, JS error with IE when the window is resizable
+                       resizable: !Ext.isIE,
+                       iconCls: buttonId,
+                       listeners: {
+                               close: {
+                                       fn: this.onClose,
+                                       scope: this
+                               }
+                       },
+                       items: [{
+                                       xtype: 'fieldset',
+                                       defaultType: 'textfield',
+                                       labelWidth: 150,
+                                       defaults: {
+                                               labelSeparator: '',
+                                               width: 250,
+                                               listeners: {
+                                                       change: {
+                                                               fn: this.clearDoc,
+                                                               scope: this
+                                                       }
+                                               }
+                                       },
+                                       listeners: {
+                                               render: {
+                                                       fn: this.initPattern,
+                                                       scope: this
+                                               }
+                                       },
+                                       items: [{
+                                                       itemId: 'pattern',
+                                                       fieldLabel: this.localize('Search for:')
+                                               },{
+                                                       itemId: 'replacement',
+                                                       fieldLabel: this.localize('Replace with:')
+                                               }
+                                       ]
+                               },{
+                                       xtype: 'fieldset',
+                                       defaultType: 'checkbox',
+                                       title: this.localize('Options'),
+                                       labelWidth: 150,
+                                       items: [{
+                                                       itemId: 'words',
+                                                       fieldLabel: this.localize('Whole words only'),
+                                                       listeners: {
+                                                               check: {
+                                                                       fn: this.clearDoc,
+                                                                       scope: this
+                                                               }
+                                                       }
+                                               },{
+                                                       itemId: 'matchCase',
+                                                       fieldLabel: this.localize('Case sensitive search'),
+                                                       listeners: {
+                                                               check: {
+                                                                       fn: this.clearDoc,
+                                                                       scope: this
+                                                               }
+                                                       }
+                                               },{
+                                                       itemId: 'replaceAll',
+                                                       fieldLabel: this.localize('Substitute all occurrences'),
+                                                       listeners: {
+                                                               check: {
+                                                                       fn: this.requestReplacement,
+                                                                       scope: this
+                                                               }
+                                                       }
+                                               }
+                                       ]
+                               },{
+                                       xtype: 'fieldset',
+                                       defaultType: 'button',
+                                       title: this.localize('Actions'),
+                                       defaults: {
+                                               minWidth: 150,
+                                               disabled: true,
+                                               style: {
+                                                       marginBottom: '5px'
+                                               }
+                                       },
+                                       items: [{
+                                                       text: this.localize('Clear'),
+                                                       itemId: 'clear',
+                                                       listeners: {
+                                                               click: {
+                                                                       fn: this.clearMarks,
+                                                                       scope: this
+                                                               }
+                                                       }
+                                               },{
+                                                       text: this.localize('Highlight'),
+                                                       itemId: 'hiliteall',
+                                                       listeners: {
+                                                               click: {
+                                                                       fn: this.hiliteAll,
+                                                                       scope: this
+                                                               }
+                                                       }
+                                               },{
+                                                       text: this.localize('Undo'),
+                                                       itemId: 'undo',
+                                                       listeners: {
+                                                               click: {
+                                                                       fn: this.resetContents,
+                                                                       scope: this
+                                                               }
+                                                       }
+                                               }
+                                       ]
+                               }
+                       ],
+                       buttons: [
+                               this.buildButtonConfig('Next', this.onNext),
+                               this.buildButtonConfig('Done', this.onCancel)
+                       ]
+               });
+               this.show();
+       },
+       /*
+        * Handler invoked to initialize the pattern to search
+        *
+        * @param       object          fieldset: the fieldset component
+        *
+        * @return      void
+        */
+       initPattern: function (fieldset) {
+               var selection = this.editor.getSelectedHTML();
+               if (/\S/.test(selection)) {
+                       selection = selection.replace(/<[^>]*>/g, '');
+                       selection = selection.replace(/&nbsp;/g, '');
                }
-               if (Ext.isOpera) {
-                       this.cleanUpRegularExpression = /(<span\s+[^>]*id=.?frmark[^>]*>)([^<>]*)(<\/span>)/gi;
-                       this.cleanUp.defer(200, this);
+               if (/\S/.test(selection)) {
+                       fieldset.getComponent('pattern').setValue(selection);
+                       fieldset.getComponent('replacement').focus();
+               } else {
+                       fieldset.getComponent('pattern').focus();
                }
-               this.dialog = this.openDialog("FindReplace", this.makeUrlFromPopupName("find_replace"), null, param, {width:this.popupWidth, height:this.popupHeight});
+       },
+       /*
+        * Handler invoked when the replace all checkbox is checked
+        */
+       requestReplacement: function () {
+               if (!this.dialog.find('itemId', 'replacement')[0].getValue() && this.dialog.find('itemId', 'replaceAll')[0].getValue()) {
+                       Ext.MessageBox.alert('', this.localize('Inform a replacement word'));
+               }
+               this.clearDoc();
+       },
+       /*
+        * Handler invoked when the 'Next' button is pressed
+        */
+       onNext: function () {
+               if (!this.dialog.find('itemId', 'pattern')[0].getValue()) {
+                       Ext.MessageBox.alert('', this.localize('Enter the text you want to find'));
+                       this.dialog.find('itemId', 'pattern')[0].focus();
+                       return false;
+               }
+               var fields = [
+                       'pattern',
+                       'replacement',
+                       'words',
+                       'matchCase',
+                       'replaceAll'
+               ];
+               var params = {};
+               Ext.each(fields, function (field) {
+                       params[field] = this.dialog.find('itemId', field)[0].getValue();
+               }, this);
+               this.search(params);
                return false;
        },
-
        /*
-        * This function cleans up any span tag left by Opera if the window was closed with the close handle in which case the unload event is not fired by Opera
+        * Search the pattern and insert span tags
+        *
+        * @param       object          params: the parameters of the search corresponding to the values of fields:
+        *                                      pattern
+        *                                      replacement
+        *                                      words
+        *                                      matchCase
+        *                                      replaceAll
+        *
+        * @return      void
+        */
+       search: function (params) {
+               var html = this.editor.getInnerHTML();
+               if (this.buffer == null) {
+                       this.buffer = html;
+               }
+               if (this.matches == 0) {
+                       var pattern = new RegExp(params.words ? '(?!<[^>]*)(\\b' + params.pattern + '\\b)(?![^<]*>)' : '(?!<[^>]*)(' + params.pattern + ')(?![^<]*>)', 'g' + (params.matchCase? '' : 'i'));
+                       this.editor.setHTML(html.replace(pattern, '<span id="htmlarea-frmark">' + "$1" + '</span>'));
+                       Ext.each(this.editor.document.body.getElementsByTagName('span'), function (mark) {
+                               if (/^htmlarea-frmark/.test(mark.id)) {
+                                       this.spans.push(mark);
+                               }
+                       }, this);
+               }
+               this.spanWalker(params.pattern, params.replacement, params.replaceAll);
+       },
+       /*
+        * Walk the span tags
+        *
+        * @param       string          pattern: the pattern being searched for
+        * @param       string          replacement: the replacement string
+        * @param       bolean          replaceAll: true if all occurrences should be replaced
         *
         * @return      void
         */
-       cleanUp : function () {
-               if (this.dialog && (!this.dialog.dialogWindow || (this.dialog.dialogWindow && this.dialog.dialogWindow.closed))) {
-                       this.editor.setHTML(this.editor.getInnerHTML().replace(this.cleanUpRegularExpression,"$2"));
-                       this.dialog.close();
+       spanWalker: function (pattern, replacement, replaceAll) {
+               this.clearMarks();
+               if (this.spans.length) {
+                       Ext.each(this.spans, function (mark, i) {
+                               if (i >= this.matches && !/[0-9]$/.test(mark.id)) {
+                                       this.matches++;
+                                       this.disableActions('clear', false);
+                                       mark.id = 'htmlarea-frmark_' + this.matches;
+                                       mark.style.color = 'white';
+                                       mark.style.backgroundColor = 'highlight';
+                                       mark.style.fontWeight = 'bold';
+                                       mark.scrollIntoView(false);
+                                       var self = this;
+                                       function replace(button) {
+                                               if (button == 'yes') {
+                                                       mark.firstChild.replaceData(0, mark.firstChild.data.length, replacement);
+                                                       self.replaces++;
+                                                       self.disableActions('undo', false);
+                                               }
+                                               self.endWalk(pattern, i);
+                                       }
+                                       if (replaceAll) {
+                                               replace('yes');
+                                               return true;
+                                       } else {
+                                               Ext.MessageBox.confirm('', this.localize('Substitute this occurrence?'), replace, this);
+                                               return false;
+                                       }
+                               }
+                       }, this);
                } else {
-                       this.cleanUp.defer(200, this);
+                       this.endWalk(pattern, 0);
+               }
+       },
+       /*
+        * End the replacement walk
+        *
+        * @param       string          pattern: the pattern being searched for
+        * @param       integer         index: the index reached in the walk
+        *
+        * @return      void
+        */
+       endWalk: function (pattern, index) {
+               if (index >= this.spans.length - 1 || !this.spans.length) {
+                       var message = this.localize('Done') + ':<br /><br />';
+                       if (this.matches > 0) {
+                               if (this.matches == 1) {
+                                       message += this.matches + ' ' + this.localize('found item');
+                               } else {
+                                       message += this.matches + ' ' + this.localize('found items');
+                               }
+                               if (this.replaces > 0) {
+                                       if (this.replaces == 1) {
+                                               message += ',<br />' + this.replaces + ' ' + this.localize('replaced item');
+                                       } else {
+                                               message += ',<br />' + this.replaces + ' ' + this.localize('replaced items');
+                                       }
+                               }
+                               this.hiliteAll();
+                       } else {
+                               message += '"' + pattern + '" ' + this.localize('not found');
+                               this.disableActions('hiliteall,clear', true);
+                       }
+                       Ext.MessageBox.minWidth = 300;
+                       Ext.MessageBox.alert('', message + '.');
+               }
+       },
+       /*
+        * Remove all marks
+        */
+       clearDoc: function () {
+               this.editor.setHTML(this.editor.getInnerHTML().replace(this.marksCleaningRE, "$2"));
+               this.initVariables();
+               this.disableActions('hiliteall,clear', true);
+       },
+       /*
+        * De-highlight all marks
+        */
+       clearMarks: function () {
+               Ext.each(this.editor.document.body.getElementsByTagName('span'), function (mark) {
+                       if (/^htmlarea-frmark/.test(mark.id)) {
+                               mark.style.backgroundColor = '';
+                               mark.style.color = '';
+                               mark.style.fontWeight = '';
+                       }
+               }, this);
+               this.disableActions('hiliteall', false);
+               this.disableActions('clear', true);
+       },
+       /*
+        * Highlight all marks
+        */
+       hiliteAll: function () {
+               Ext.each(this.editor.document.body.getElementsByTagName('span'), function (mark) {
+                       if (/^htmlarea-frmark/.test(mark.id)) {
+                               mark.style.backgroundColor = 'highlight';
+                               mark.style.color = 'white';
+                               mark.style.fontWeight = 'bold';
+                       }
+               }, this);
+               this.disableActions('clear', false);
+               this.disableActions('hiliteall', true);
+       },
+       /*
+        * Undo the replace operation
+        */
+       resetContents: function () {
+               if (this.buffer != null) {
+                       var transp = this.editor.getInnerHTML();
+                       this.editor.setHTML(this.buffer);
+                       this.buffer = transp;
+                       this.disableActions('clear', true);
+               }
+       },
+       /*
+        * Disable action buttons
+        *
+        * @param       array           actions: array of buttonIds to set disabled/enabled
+        * @param       boolean         disabled: true to set disabled
+        */
+       disableActions: function (actions, disabled) {
+               Ext.each(actions.split(/[,; ]+/), function (action) {
+                               this.dialog.find('itemId', action)[0].setDisabled(disabled);
+               }, this);
+       },
+       /*
+        * Initialize find & replace variables
+        */
+       initVariables: function () {
+               this.matches = 0;
+               this.replaces = 0;
+               this.spans = new Array();
+       },
+       /*
+        * Clear the document before leaving on 'Done' button
+        */
+       onCancel: function () {
+               this.clearDoc();
+               var plugin = this.getPluginInstance('UndoRedo');
+               if (plugin) {
+                       plugin.start();
+               }
+               this.base();
+       },
+       /*
+        * Clear the document before leaving on window close handle
+        */
+       onClose: function () {
+               this.clearDoc();
+               var plugin = this.getPluginInstance('UndoRedo');
+               if (plugin) {
+                       plugin.start();
                }
+               this.base();
        }
 });
diff --git a/typo3/sysext/rtehtmlarea/htmlarea/plugins/FindReplace/fr_engine.js b/typo3/sysext/rtehtmlarea/htmlarea/plugins/FindReplace/fr_engine.js
deleted file mode 100644 (file)
index 8104f10..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-/*---------------------------------------*\
- Find and Replace Plugin for HTMLArea-3.0
- -----------------------------------------
- author: Cau guanabara 
- e-mail: caugb@ibest.com.br
-\*---------------------------------------*/
-
-       var tosearch = '';
-       var pater = null;
-       var buffer = null;
-       var matches = 0;
-       var replaces = 0;
-       var fr_spans = new Array();
-               
-       function execSearch (params) {
-               var ihtml = dialog.plugin.getPluginInstance("EditorMode").getInnerHTML();
-               if (buffer == null) {
-                       buffer = ihtml;
-               }
-               
-               if (params.fr_pattern != tosearch) {
-                       if (tosearch != "") {
-                               clearDoc();
-                       }
-                       tosearch = params.fr_pattern;
-               }
-               
-               if (matches == 0) {
-                       er = params.fr_words ? "/(?!<[^>]*)(\\b"+params.fr_pattern+"\\b)(?![^<]*>)/g" : "/(?!<[^>]*)("+params.fr_pattern+")(?![^<]*>)/g";
-                       if (!params.fr_matchcase) {
-                               er += "i";
-                       }
-                       
-                       pater = eval(er);
-                       
-                       var tago = '<span id=frmark>';
-                       var tagc = '</span>';
-                       var newHtml = ihtml.replace(pater,tago+"$1"+tagc);
-                       dialog.plugin.getPluginInstance("EditorMode").setHTML(newHtml);
-                       
-                       var getallspans = editor._doc.body.getElementsByTagName("span");
-                       for (var i = 0; i < getallspans.length; i++) {
-                               if (/^frmark/.test(getallspans[i].id)) {
-                                       fr_spans.push(getallspans[i]);
-                               }
-                       }
-               }
-               spanWalker(params['fr_pattern'],params['fr_replacement'],params['fr_replaceall']);
-       };
-       
-       function spanWalker (pattern,replacement,replaceall) {
-               var foundtrue = false;
-               clearMarks();
-               
-               for (var i = matches; i < fr_spans.length; i++) {
-                       var elm = fr_spans[i];
-                       foundtrue = true;
-                       if (!(/[0-9]$/.test(elm.id))) {
-                               matches++;
-                               disable('fr_clear', false);
-                               elm.id = 'frmark_'+ matches;
-                               elm.style.color = 'white';
-                               elm.style.backgroundColor = 'highlight';
-                               elm.style.fontWeight = 'bold';
-                               elm.scrollIntoView(false);
-                               if (replaceall || confirm(dialog.plugin.localize("Substitute this occurrence?"))) {
-                                       elm.firstChild.replaceData(0,elm.firstChild.data.length,replacement);
-                                       replaces++;
-                                       disable('fr_undo', false);
-                               }
-                               if (replaceall) {
-                                       clearMarks();
-                                       continue;
-                               }
-                               break;
-                       }
-               }
-               var last = (i >= fr_spans.length - 1);
-               if (last || !foundtrue) { // EOF
-                       var message = dialog.plugin.localize("Done")+":\n\n";
-                       if (matches > 0) {
-                               if (matches == 1) {
-                                       message += matches+' ' + dialog.plugin.localize("found item");
-                               } else {
-                                       message += matches+' ' + dialog.plugin.localize("found items");
-                               }
-                               if (replaces > 0) {
-                                       if (replaces == 1) {
-                                               message += ',\n'+replaces+' ' + dialog.plugin.localize("replaced item");
-                                       } else {
-                                               message += ',\n'+replaces+' ' + dialog.plugin.localize("replaced items");
-                                       }
-                               }
-                               hiliteAll();
-                               disable('fr_hiliteall', false);
-                       } else {
-                               message += '"' + pattern + '" ' + dialog.plugin.localize("not found");
-                       }
-                       alert(message+'.');
-               }
-       };
-       
-       function clearDoc () {
-               var er = /(<span\s+[^>]*id=.?frmark[^>]*>)([^<>]*)(<\/span>)/gi;
-               dialog.plugin.getPluginInstance("EditorMode").setHTML(dialog.plugin.getPluginInstance("EditorMode").getInnerHTML().replace(er,"$2"));
-               pater = null;
-               tosearch = '';
-               fr_spans = new Array();
-               matches = 0;
-               replaces = 0;
-               disable("fr_hiliteall,fr_clear", true);
-       };
-       
-       function clearMarks () {
-               var getall = editor._doc.body.getElementsByTagName("span");
-               for (var i = 0; i < getall.length; i++) {
-                       var elm = getall[i];
-                       if (/^frmark/.test(elm.id)) {
-                               var objStyle = editor._doc.getElementById(elm.id).style;
-                               objStyle.backgroundColor = "";
-                               objStyle.color = "";
-                               objStyle.fontWeight = "";
-                       }
-               }
-       };
-       
-       function hiliteAll () {
-               var getall = editor._doc.body.getElementsByTagName("span");
-               for (var i = 0; i < getall.length; i++) {
-                       var elm = getall[i];
-                       if (/^frmark/.test(elm.id)) {
-                               var objStyle = editor._doc.getElementById(elm.id).style;
-                               objStyle.backgroundColor = "highlight";
-                               objStyle.color = "white";
-                               objStyle.fontWeight = "bold";
-                       }
-               }
-       };
-       
-       function resetContents () {
-               if (buffer != null) {
-                       var transp = dialog.plugin.getPluginInstance("EditorMode").getInnerHTML();
-                       dialog.plugin.getPluginInstance("EditorMode").setHTML(buffer);
-                       buffer = transp;
-               }
-       };
-       
-       function disable (elms, toset) {
-               var names = elms.split(/[,; ]+/);
-               for (var i = 0; i < names.length; i++) {
-                       document.getElementById(names[i]).disabled = toset;
-               }
-       };
-       
index 7f90c22..81ce01c 100644 (file)
                        <label index="replaced item">item replaced</label>
                        <label index="not found">not found</label>
                        <label index="Find and Replace">Find And Replace</label>
-                       <label index="Options">Options:</label>
+                       <label index="Options">Options</label>
                        <label index="Whole words only">Whole words only</label>
                        <label index="Case sensitive search">Case sensitive search</label>
                        <label index="Substitute all occurrences">Substitute all occurrences</label>
                        <label index="Search for:">Search for:</label>
                        <label index="Replace with:">Replace with:</label>
-                       <label index="Actions">Actions:</label>
+                       <label index="Actions">Actions</label>
                        <label index="Clear">Clear</label>
                        <label index="Highlight">Highlight</label>
                        <label index="Undo">Undo</label>
diff --git a/typo3/sysext/rtehtmlarea/htmlarea/plugins/FindReplace/popups/find_replace.html b/typo3/sysext/rtehtmlarea/htmlarea/plugins/FindReplace/popups/find_replace.html
deleted file mode 100644 (file)
index a855227..0000000
+++ /dev/null
@@ -1,183 +0,0 @@
-<!DOCTYPE html
-     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
-     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html>
-<!--
-/***************************************************************
-*  Copyright notice
-*
-*  (c) 2004 Cau guanabara <caugb@ibest.com.br>
-*  (c) 2005-2008 Stanislas Rolland <typo3(arobas)sjbr.ca>
-*  All rights reserved
-*
-*  This script is part of the TYPO3 project. The TYPO3 project is
-*  free software; you can redistribute it and/or modify
-*  it under the terms of the GNU General Public License as published by
-*  the Free Software Foundation; either version 2 of the License, or
-*  (at your option) any later version.
-*
-*  The GNU General Public License can be found at
-*  http://www.gnu.org/copyleft/gpl.html.
-*  A copy is found in the textfile GPL.txt and important notices to the license
-*  from the author is found in LICENSE.txt distributed with these scripts.
-*
-*
-*  This script is distributed in the hope that it will be useful,
-*  but WITHOUT ANY WARRANTY; without even the implied warranty of
-*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-*  GNU General Public License for more details.
-*
-*  This script is a modified version of a script published under the htmlArea License.
-*  A copy of the htmlArea License may be found in the textfile HTMLAREA_LICENSE.txt.
-*
-*  This copyright notice MUST APPEAR in all copies of the script!
-***************************************************************/
-/*
- * Find and Replace Plugin for TYPO3 htmlArea RTE
- *
- * TYPO3 SVN ID: $Id$
- */
--->
-<head>
-       <title>Find and Replace</title>
-       <meta http-equiv="Content-Style-Type" content="text/css" />
-       <script type="text/javascript" src="../fr_engine.js"></script>
-       <script type="text/javascript">
-               /*<![CDATA[*/
-               <!--
-               var dialog = window.opener.HTMLArea.Dialog.FindReplace;
-               var editor;
-               var accepted = {
-                       'fr_pattern'       : true,
-                       'fr_replacement'   : true,
-                       'fr_words'         : true,
-                       'fr_matchcase'     : true,
-                       'fr_replaceall'    : true
-               };
-
-               function Init() {
-                       editor = dialog.plugin.editor;
-                       disable("fr_undo,fr_clear,fr_hiliteall", true);
-
-                       var params = dialog.arguments;
-                       if (params) {
-                               document.getElementById('fr_pattern').value = params.fr_pattern;
-                               document.getElementById('fr_replacement').focus();
-                       } else {
-                               document.getElementById('fr_pattern').focus();
-                       }
-                       window.opener.HTMLArea._addEvent(document, "keypress", onKeyPress);
-                       if (window.opener.HTMLArea.is_gecko) {
-                               window.opener.HTMLArea._addEvent(window, "unload", onCancel);
-                       }
-                       dialog.initialize();
-                       if (HTMLArea.is_ie) {
-                               HTMLArea._addEvent(window, "unload", onCancel);
-                       }
-               };
-               function requestReplacement() {
-                       if (!document.getElementById("fr_replacement").value && document.getElementById("fr_replaceall").checked) {
-                               return confirm(dialog.plugin.localize("Inform a replacement word"));
-                       }
-                       clearDoc();
-               }
-               function onCancel() {
-                       if (dialog) {
-                               clearDoc();
-                               HTMLArea._removeEvent(document, "keypress", onKeyPress);
-                               HTMLArea._removeEvent(window, "unload", onCancel);
-                               dialog.close();
-                       }
-                       return false;
-               };
-               function onOK() {
-                       var required = {'fr_pattern' : dialog.plugin.localize("Enter the text you want to find")};
-                       for (var i in required) {
-                               var el = document.getElementById(i);
-                               if (!el.value) {
-                                       alert(required[i]);
-                                       el.focus();
-                                       return false;
-                               }
-                       }
-
-                       var param = {};
-                       for (var i in accepted) {
-                               var el = document.getElementById(i);
-                               param[i] = (el.type == "checkbox") ? el.checked : el.value;
-                       }
-                       execSearch(param);
-                       return false;
-               };
-               function onEscape(ev) {
-                       if (!ev) var ev = window.event;
-                       if (ev.keyCode == 27) {
-                               return onCancel();
-                       }
-                       return true;
-               };
-               function onKeyPress (ev) {
-                       if (!ev) var ev = window.event;
-                       switch(ev.keyCode) {
-                               case 13:
-                                       document.getElementById('fr_go').click();
-                                       document.getElementById('fr_pattern').focus();
-                                       break;
-                               case 27:
-                                       return onCancel();
-                       }
-                       return true;
-               };
-               // -->
-               /*]]>*/
-       </script>
-</head>
-<body class="popupwin htmlarea-find-replace" onload="Init();">
-<div id="content">
-<div class="title">Find and Replace</div>
-<form action="" method="get">
-       <fieldset>
-               <div>
-                       <label for="fr_pattern">Search for:</label><br />
-                       <input id="fr_pattern" type="text" size="35" onFocus="this.select();">
-               </div>
-               <div>
-                       <label for="fr_replacement">Replace with:</label><br />
-                       <input id="fr_replacement" type="text" size="35" onFocus="this.select();">
-               </div>
-       </fieldset>
-       <fieldset>
-               <legend>Options</legend>
-               <div>
-                               <input id="fr_words" type="checkbox" checked="checked" onClick="clearDoc();">
-                               <label for="fr_words" class="long-label">Whole words only</label>
-               </div>
-               <div>
-                               <input id="fr_matchcase" type="checkbox" onClick="clearDoc();">
-                               <label for="fr_matchcase" class="long-label">Case sensitive search</label>
-               </div>
-               <div>
-                               <input id="fr_replaceall" type="checkbox" onClick="requestReplacement();">
-                               <label for="fr_replaceall" class="long-label">Substitute all occurrences</label>
-               </div>
-       </fieldset>
-       <fieldset>
-               <legend>Actions</legend>
-               <div>
-                               <button type="button" class="long-button" id="fr_clear" onClick="clearMarks();">Clear</button>
-               </div>
-               <div>
-                               <button type="button" class="long-button" id="fr_hiliteall" onClick="hiliteAll();">Highlight</button>
-               </div>
-               <div>
-                               <button type="button" class="long-button" id="fr_undo" onClick="resetContents();">Undo</button>
-               </div>
-       </fieldset>
-       <div class="buttons">
-               <button type="button" id="fr_go" onclick="return onOK();">Next</button>
-               <button type="button" name="cancel" onclick="return onCancel();">Done</button>
-       </div>
-</form>
-</div>
-</body>
-</html>
index 0f4762a..7e228a0 100644 (file)
  * TYPO3 SVN ID: $Id$
  */
 UndoRedo = HTMLArea.Plugin.extend({
-       
-       constructor : function (editor, pluginName) {
+       constructor: function (editor, pluginName) {
                this.base(editor, pluginName);
        },
-       
        /*
         * This function gets called by the class constructor
         */
-       configurePlugin : function (editor) {
-               
+       configurePlugin: function (editor) {
                this.pageTSconfiguration = this.editorConfiguration.buttons.undo;
                this.customUndo = true;
                this.undoQueue = new Array();
@@ -50,21 +47,19 @@ UndoRedo = HTMLArea.Plugin.extend({
                this.undoSteps = 25;
                        // The time interval at which undo samples are taken: 1/2 sec.
                this.undoTimeout = 500;
-               
                /*
                 * Registering plugin "About" information
                 */
                var pluginInformation = {
-                       version         : "1.1",
-                       developer       : "Stanislas Rolland",
-                       developerUrl    : "http://www.sjbr.ca",
-                       copyrightOwner  : "Stanislas Rolland",
-                       sponsor         : "SJBR",
-                       sponsorUrl      : "http://www.sjbr.ca",
-                       license         : "GPL"
+                       version         : '2.0',
+                       developer       : 'Stanislas Rolland',
+                       developerUrl    : 'http://www.sjbr.ca',
+                       copyrightOwner  : 'Stanislas Rolland',
+                       sponsor         : 'SJBR',
+                       sponsorUrl      : 'http://www.sjbr.ca',
+                       license         : 'GPL'
                };
                this.registerPluginInformation(pluginInformation);
-               
                /*
                 * Registering the buttons
                 */
@@ -75,42 +70,55 @@ UndoRedo = HTMLArea.Plugin.extend({
                        var buttonConfiguration = {
                                id              : buttonId,
                                tooltip         : this.localize(buttonId.toLowerCase()),
-                               action          : "onButtonPress",
+                               action          : 'onButtonPress',
                                hotKey          : (this.editorConfiguration.buttons[buttonId.toLowerCase()]?this.editorConfiguration.buttons[buttonId.toLowerCase()].hotKey:button[2]),
                                noAutoUpdate    : true
                        };
                        this.registerButton(buttonConfiguration);
                }
-               
                return true;
        },
-       
        /*
         * The list of buttons added by this plugin
         */
-       buttonList : [
-               ["Undo", null, "z"],
-               ["Redo", null, "y"]
+       buttonList: [
+               ['Undo', null, 'z'],
+               ['Redo', null, 'y']
        ],
-       
        /*
         * This function gets called when the editor is generated
         */
        onGenerate: function () {
                        // Start undo snapshots
                if (this.customUndo) {
-                       Ext.TaskMgr.start({
+                       this.task = {
                                run: this.takeSnapshot,
                                scope: this,
                                interval: this.undoTimeout
-                       });
+                       };
+                       this.start();
+               }
+       },
+       /*
+        * Start the undo/redo snapshot task
+        */
+       start: function () {
+               if (this.customUndo) {
+                       Ext.TaskMgr.start(this.task);
+               }
+       },
+       /*
+        * Start the undo/redo snapshot task
+        */
+       stop: function () {
+               if (this.customUndo) {
+                       Ext.TaskMgr.stop(this.task);
                }
        },
-       
        /*
         * Take a snapshot of the current contents for undo
         */
-       takeSnapshot : function () {
+       takeSnapshot: function () {
                var currentTime = (new Date()).getTime();
                var newSnapshot = false;
                if (this.undoPosition >= this.undoSteps) {
@@ -146,7 +154,6 @@ UndoRedo = HTMLArea.Plugin.extend({
                        }
                }
        },
-
        /*
         * Build the snapshot entry
         *
@@ -155,17 +162,17 @@ UndoRedo = HTMLArea.Plugin.extend({
         *                              - bookmark (the bookmark),
         *                              - bookmarkedText (the content of the RTE including the bookmark)
         */
-       buildSnapshot : function () {
+       buildSnapshot: function () {
                var bookmark = null, bookmarkedText = null;
                        // Insert a bookmark
-               if (this.editor.getMode() == "wysiwyg" && this.editor.isEditable()) {
+               if (this.editor.getMode() == 'wysiwyg' && this.editor.isEditable()) {
                        var selection = this.editor._getSelection();
-                       if ((HTMLArea.is_gecko && !HTMLArea.is_opera9) || (HTMLArea.is_ie && selection.type.toLowerCase() != "control")) {
+                       if ((HTMLArea.is_gecko && !HTMLArea.is_opera9) || (HTMLArea.is_ie && selection.type.toLowerCase() != 'control')) {
                                        // Catch error in FF when the selection contains no usable range
                                try {
                                                // Work around IE8 bug: can't create a range correctly if the selection is empty and the focus is not on the editor window
                                                // But we cannot grab focus from an opened window just for the sake of taking this bookmark
-                                       if (!HTMLArea.is_ie || !this.editor.hasOpenedWindow() || selection.type.toLowerCase() != "none") {
+                                       if (!HTMLArea.is_ie || !this.editor.hasOpenedWindow() || selection.type.toLowerCase() != 'none') {
                                                bookmark = this.editor.getBookmark(this.editor._createRange(selection));
                                        }
                                } catch (e) {
@@ -189,11 +196,10 @@ UndoRedo = HTMLArea.Plugin.extend({
                        bookmarkedText  : bookmarkedText
                };
        },
-       
        /*
         * Execute the undo request
         */
-       undo : function () {
+       undo: function () {
                if (this.undoPosition > 0) {
                                // Make sure we would not loose any changes
                        this.takeSnapshot();
@@ -201,11 +207,10 @@ UndoRedo = HTMLArea.Plugin.extend({
                        this.updateButtonsState();
                }
        },
-       
        /*
         * Execute the redo request
         */
-       redo : function () {
+       redo: function () {
                if (this.undoPosition < this.undoQueue.length - 1) {
                                // Make sure we would not loose any changes
                        this.takeSnapshot();
@@ -216,11 +221,10 @@ UndoRedo = HTMLArea.Plugin.extend({
                        }
                }
        },
-       
        /*
         * Set content using undo queue position
         */
-       setContent : function (undoPosition) {
+       setContent: function (undoPosition) {
                var bookmark = this.undoQueue[undoPosition].bookmark;
                if (bookmark) {
                        this.editor.setHTML(this.undoQueue[undoPosition].bookmarkedText);
@@ -231,7 +235,6 @@ UndoRedo = HTMLArea.Plugin.extend({
                        this.editor.setHTML(this.undoQueue[undoPosition].text);
                }
        },
-       
        /*
         * This function gets called when the toolbar is updated
         */
@@ -257,7 +260,6 @@ UndoRedo = HTMLArea.Plugin.extend({
                        button.setDisabled(!button.textMode);
                }
        },
-       
        /*
         * Update the state of the undo/redo buttons
         */
@@ -278,7 +280,6 @@ UndoRedo = HTMLArea.Plugin.extend({
                        this.onUpdateToolbar(button, mode, selectionEmpty, ancestors)
                }
        },
-       
        /*
         * This function gets called when the button was pressed.
         *
@@ -287,7 +288,7 @@ UndoRedo = HTMLArea.Plugin.extend({
         *
         * @return      boolean         false if action is completed
         */
-       onButtonPress : function (editor, id) {
+       onButtonPress: function (editor, id) {
                        // Could be a button or its hotkey
                var buttonId = this.translateHotKey(id);
                buttonId = buttonId ? buttonId : id;
index 6a54179..7ef0c54 100644 (file)
 }
 .htmlarea-window .x-form-item-label {
        text-align: right;
-       vertical-align: middle;
-       padding: 4px 5px 0 5px;
+       padding: 3px 5px 0 5px;
 }
 .htmlarea-window .x-btn-text {
        font-weight: normal;
        color: #000000;
 }
-.htmlarea-window .x-form-check-wrap input {
-       vertical-align: middle;
+.htmlarea-window .x-form-check-wrap {
+       padding-top: 3px;
 }
 .htmlarea-window .show-color {
        margin-top: 10px;
        height: 20px;
        vertical-align: middle;
 }
-/* Selectors for the FindReplace dialogue */
-.htmlarea-find-replace .long-label {
-       text-align:left;
-       width:30em;
-}
 /* Selectors for the CharacterMap dialogue */
 .htmlarea-window .character-map .character {
        display: block;
index 6ff8ffa..d05f860 100644 (file)
 }
 .htmlarea-window .x-form-item-label {
        text-align: right;
-       vertical-align: middle;
-       padding: 4px 5px 0 5px;
+       padding: 3px 5px 0 5px;
 }
 .htmlarea-window .x-btn-text {
        font-weight: normal;
        color: #000000;
 }
-.htmlarea-window .x-form-check-wrap input {
-       vertical-align: middle;
+.htmlarea-window .x-form-check-wrap {
+       padding-top: 3px;
 }
 .htmlarea-window .show-color {
        margin-top: 10px;
        height: 20px;
        vertical-align: middle;
 }
-/* Selectors for the FindReplace dialogue */
-.htmlarea-find-replace .long-label {
-       text-align:left;
-       width:30em;
-}
 /* Selectors for the CharacterMap dialogue */
 .htmlarea-window .character-map .character {
        display: block;