[TASK] RTE: Remove dependency on class Ext.Observable 50/35150/3
authorStanislas Rolland <typo3@sjbr.ca>
Mon, 8 Dec 2014 01:55:06 +0000 (20:55 -0500)
committerStanislas Rolland <typo3@sjbr.ca>
Mon, 8 Dec 2014 02:05:09 +0000 (03:05 +0100)
RTE classes Editor and CSS.Parser extend Ext.Observable.
Since event handling was migrated to jQuery, this is not necessary anymore.

Releases: master
Resolves: #63654
Change-Id: I6c9287ea7f1dc0e785571c98f8fb604a2a7f959a
Reviewed-on: http://review.typo3.org/35150
Reviewed-by: Stanislas Rolland <typo3@sjbr.ca>
Tested-by: Stanislas Rolland <typo3@sjbr.ca>
typo3/sysext/rtehtmlarea/Resources/Public/JavaScript/HTMLArea/CSS/Parser.js
typo3/sysext/rtehtmlarea/Resources/Public/JavaScript/HTMLArea/Editor/Editor.js
typo3/sysext/rtehtmlarea/Resources/Public/JavaScript/Plugins/ContextMenu.js

index 6bcecb0..36919d6 100644 (file)
@@ -19,369 +19,363 @@ define('TYPO3/CMS/Rtehtmlarea/HTMLArea/CSS/Parser',
        'TYPO3/CMS/Rtehtmlarea/HTMLArea/Event/Event'],
        function (UserAgent, Util, Event) {
 
-       var Parser = Ext.extend(Ext.util.Observable, {
-
-               /**
-                * Parser constructor
-                */
-               constructor: function (config) {
-                       Parser.superclass.constructor.call(this, {});
-                       var configDefaults = {
-                               parseAttemptsMaximumNumber: 20,
-                               prefixLabelWithClassName: false,
-                               postfixLabelWithClassName: false,
-                               showTagFreeClasses: false,
-                               tags: null,
-                               editor: null
-                       };
-                       Util.apply(this, config, configDefaults);
-                       if (this.editor.config.styleSheetsMaximumAttempts) {
-                               this.parseAttemptsMaximumNumber = this.editor.config.styleSheetsMaximumAttempts;
-                       }
-                       this.parsedClasses = {};
-                       this.ready = false;
-               },
+       /**
+        * Parser constructor
+        */
+       var Parser = function (config) {
+               var configDefaults = {
+                       parseAttemptsMaximumNumber: 20,
+                       prefixLabelWithClassName: false,
+                       postfixLabelWithClassName: false,
+                       showTagFreeClasses: false,
+                       tags: null,
+                       editor: null
+               };
+               Util.apply(this, config, configDefaults);
+               if (this.editor.config.styleSheetsMaximumAttempts) {
+                       this.parseAttemptsMaximumNumber = this.editor.config.styleSheetsMaximumAttempts;
+               }
 
                /**
                 * The parsed classes
                 */
-               parsedClasses: {},
+               this.parsedClasses = {};
 
                /**
                 * Boolean indicating whether are not parsing is complete
                 */
-               ready: false,
+               this.ready = false;
 
                /**
                 * Boolean indicating whether or not the stylesheets were accessible
                 */
-               cssLoaded: false,
+               this.cssLoaded = false;
 
                /**
                 * Counter of the number of attempts at parsing the stylesheets
                 */
-               parseAttemptsCounter: 0,
+               this.parseAttemptsCounter = 0;
 
                /**
                 * Parsing attempt timeout id
                 */
-               attemptTimeout: null,
+               this.attemptTimeout = null;
 
                /**
                 * The error that occurred on the last attempt at parsing the stylesheets
                 */
-               error: null,
+               this.error = null;
+       };
 
-               /**
-                * This function gets the parsed css classes
-                *
-                * @return      object  this.parsedClasses
-                */
-               getClasses: function() {
-                       return this.parsedClasses;
-               },
+       /**
+        * This function gets the parsed css classes
+        *
+        * @return object this.parsedClasses
+        */
+       Parser.prototype.getClasses = function() {
+               return this.parsedClasses;
+       };
 
-               /**
-                * This function gets the ready state
-                *
-                * @return bool this.ready
-                */
-               isReady: function() {
-                       return this.ready;
-               },
+       /**
+        * This function gets the ready state
+        *
+        * @return bool this.ready
+        */
+       Parser.prototype.isReady = function() {
+               return this.ready;
+       };
 
-               /**
-                * This function parses the stylesheets of the iframe set in config
-                *
-                * @return      void    parsed css classes are accumulated in this.parsedClasses
-                */
-               parse: function() {
-                       if (this.editor.document) {
-                               this.parseStyleSheets();
-                               if (!this.cssLoaded) {
-                                       if (/Security/i.test(this.error)) {
-                                               this.editor.appendToLog('HTMLArea.CSS.Parser', 'parse', 'A security error occurred. Make sure all stylesheets are accessed from the same domain/subdomain and using the same protocol as the current script.', 'error');
-                                               /**
-                                                * @event HTMLAreaEventCssParsingComplete
-                                                * Fires when parsing of the stylesheets of the iframe is complete
-                                                */
-                                               Event.trigger(this, 'HTMLAreaEventCssParsingComplete');
-                                       } else if (this.parseAttemptsCounter < this.parseAttemptsMaximumNumber) {
-                                               this.parseAttemptsCounter++;
-                                               var self = this;
-                                               this.attemptTimeout = window.setTimeout(function () {
-                                                       self.parse();
-                                               }, 200);
-                                       } else {
-                                               this.editor.appendToLog('HTMLArea.CSS.Parser', 'parse', 'The stylesheets could not be parsed. Reported error: ' + this.error, 'error');
-                                               /**
-                                                * @event HTMLAreaEventCssParsingComplete
-                                                * Fires when parsing of the stylesheets of the iframe is complete
-                                                */
-                                               Event.trigger(this, 'HTMLAreaEventCssParsingComplete');
-                                       }
+       /**
+        * This function parses the stylesheets of the iframe set in config
+        *
+        * @return void parsed css classes are accumulated in this.parsedClasses
+        */
+       Parser.prototype.parse = function() {
+               if (this.editor.document) {
+                       this.parseStyleSheets();
+                       if (!this.cssLoaded) {
+                               if (/Security/i.test(this.error)) {
+                                       this.editor.appendToLog('HTMLArea.CSS.Parser', 'parse', 'A security error occurred. Make sure all stylesheets are accessed from the same domain/subdomain and using the same protocol as the current script.', 'error');
+                                       /**
+                                        * @event HTMLAreaEventCssParsingComplete
+                                        * Fires when parsing of the stylesheets of the iframe is complete
+                                        */
+                                       Event.trigger(this, 'HTMLAreaEventCssParsingComplete');
+                               } else if (this.parseAttemptsCounter < this.parseAttemptsMaximumNumber) {
+                                       this.parseAttemptsCounter++;
+                                       var self = this;
+                                       this.attemptTimeout = window.setTimeout(function () {
+                                               self.parse();
+                                       }, 200);
                                } else {
-                                       this.attemptTimeout = null;
-                                       this.ready = true;
-                                       this.filterAllowedClasses();
-                                       this.sort();
+                                       this.editor.appendToLog('HTMLArea.CSS.Parser', 'parse', 'The stylesheets could not be parsed. Reported error: ' + this.error, 'error');
                                        /**
                                         * @event HTMLAreaEventCssParsingComplete
                                         * Fires when parsing of the stylesheets of the iframe is complete
                                         */
                                        Event.trigger(this, 'HTMLAreaEventCssParsingComplete');
                                }
+                       } else {
+                               this.attemptTimeout = null;
+                               this.ready = true;
+                               this.filterAllowedClasses();
+                               this.sort();
+                               /**
+                                * @event HTMLAreaEventCssParsingComplete
+                                * Fires when parsing of the stylesheets of the iframe is complete
+                                */
+                               Event.trigger(this, 'HTMLAreaEventCssParsingComplete');
                        }
-               },
+               }
+       };
 
-               /**
-                * This function parses the stylesheets of an iframe
-                *
-                * @return      void    parsed css classes are accumulated in this.parsedClasses
-                */
-               parseStyleSheets: function () {
-                       this.cssLoaded = true;
-                       this.error = null;
-                               // Test if the styleSheets array is at all accessible
-                       if (UserAgent.isOpera) {
-                               if (this.editor.document.readyState !== 'complete') {
+       /**
+        * This function parses the stylesheets of an iframe
+        *
+        * @return void parsed css classes are accumulated in this.parsedClasses
+        */
+       Parser.prototype.parseStyleSheets = function () {
+               this.cssLoaded = true;
+               this.error = null;
+               // Test if the styleSheets array is at all accessible
+               if (UserAgent.isOpera) {
+                       if (this.editor.document.readyState !== 'complete') {
+                               this.cssLoaded = false;
+                               this.error = 'Document.readyState not complete';
+                       }
+               } else {
+                       if (UserAgent.isIEBeforeIE9) {
+                               try {
+                                       var rules = this.editor.document.styleSheets[0].rules;
+                                       var imports = this.editor.document.styleSheets[0].imports;
+                                       if (!rules.length && !imports.length) {
+                                               this.cssLoaded = false;
+                                               this.error = 'Empty rules and imports arrays';
+                                       }
+                               } catch(e) {
                                        this.cssLoaded = false;
-                                       this.error = 'Document.readyState not complete';
+                                       this.error = e;
                                }
                        } else {
-                               if (UserAgent.isIEBeforeIE9) {
-                                       try {
-                                               var rules = this.editor.document.styleSheets[0].rules;
-                                               var imports = this.editor.document.styleSheets[0].imports;
-                                               if (!rules.length && !imports.length) {
-                                                       this.cssLoaded = false;
-                                                       this.error = 'Empty rules and imports arrays';
-                                               }
-                                       } catch(e) {
-                                               this.cssLoaded = false;
-                                               this.error = e;
-                                       }
-                               } else {
-                                       try {
-                                               this.editor.document.styleSheets && this.editor.document.styleSheets[0] && this.editor.document.styleSheets[0].rules;
-                                       } catch(e) {
-                                               this.cssLoaded = false;
-                                               this.error = e;
-                                       }
+                               try {
+                                       this.editor.document.styleSheets && this.editor.document.styleSheets[0] && this.editor.document.styleSheets[0].rules;
+                               } catch(e) {
+                                       this.cssLoaded = false;
+                                       this.error = e;
                                }
                        }
-                       if (this.cssLoaded) {
-                                       // Expecting at least 2 stylesheets...
-                               if (this.editor.document.styleSheets.length > 1) {
-                                       var styleSheets = this.editor.document.styleSheets;
-                                       for (var index = 0, n = styleSheets.length; index < n; index++) {
-                                               try {
-                                                       var styleSheet = styleSheets[index];
-                                                       if (UserAgent.isIEBeforeIE9) {
-                                                               var rules = styleSheet.rules;
-                                                               var imports = styleSheet.imports;
-                                                               if (!rules.length && !imports.length) {
-                                                                       this.cssLoaded = false;
-                                                                       this.error = 'Empty rules and imports arrays of styleSheets[' + index + ']';
-                                                                       break;
-                                                               }
-                                                               if (styleSheet.imports) {
-                                                                       this.parseIeRules(styleSheet.imports);
-                                                               }
-                                                               if (styleSheet.rules) {
-                                                                       this.parseRules(styleSheet.rules);
-                                                               }
-                                                       } else {
-                                                               this.parseRules(styleSheet.cssRules);
+               }
+               if (this.cssLoaded) {
+                       // Expecting at least 2 stylesheets...
+                       if (this.editor.document.styleSheets.length > 1) {
+                               var styleSheets = this.editor.document.styleSheets;
+                               for (var index = 0, n = styleSheets.length; index < n; index++) {
+                                       try {
+                                               var styleSheet = styleSheets[index];
+                                               if (UserAgent.isIEBeforeIE9) {
+                                                       var rules = styleSheet.rules;
+                                                       var imports = styleSheet.imports;
+                                                       if (!rules.length && !imports.length) {
+                                                               this.cssLoaded = false;
+                                                               this.error = 'Empty rules and imports arrays of styleSheets[' + index + ']';
+                                                               break;
+                                                       }
+                                                       if (styleSheet.imports) {
+                                                               this.parseIeRules(styleSheet.imports);
                                                        }
-                                               } catch (e) {
-                                                       this.error = e;
-                                                       this.cssLoaded = false;
-                                                       this.parsedClasses = {};
-                                                       break;
+                                                       if (styleSheet.rules) {
+                                                               this.parseRules(styleSheet.rules);
+                                                       }
+                                               } else {
+                                                       this.parseRules(styleSheet.cssRules);
                                                }
+                                       } catch (e) {
+                                               this.error = e;
+                                               this.cssLoaded = false;
+                                               this.parsedClasses = {};
+                                               break;
                                        }
-                               } else {
-                                       this.cssLoaded = false;
-                                       this.error = 'Empty stylesheets array or missing linked stylesheets';
                                }
+                       } else {
+                               this.cssLoaded = false;
+                               this.error = 'Empty stylesheets array or missing linked stylesheets';
                        }
-               },
+               }
+       };
 
-               /**
-                * This function parses the set of rules from a standard stylesheet
-                *
-                * @param       array           cssRules: the array of rules of a stylesheet
-                * @return      void
-                */
-               parseRules: function (cssRules) {
-                       for (var rule = 0, n = cssRules.length; rule < n; rule++) {
-                                       // Style rule
-                               if (cssRules[rule].selectorText) {
-                                       this.parseSelectorText(cssRules[rule].selectorText);
-                               } else {
-                                               // Import rule
-                                       try {
-                                               if (cssRules[rule].styleSheet && cssRules[rule].styleSheet.cssRules) {
-                                                               this.parseRules(cssRules[rule].styleSheet.cssRules);
-                                               }
-                                       } catch (e) {
-                                               if (/Security/i.test(e)) {
-                                                       // If this is a security error, silently log the error and continue parsing
-                                                       this.editor.appendToLog('HTMLArea.CSS.Parser', 'parseRules', 'A security error occurred. Make sure all stylesheets are accessed from the same domain/subdomain and using the same protocol as the current script.', 'error');
-                                               } else {
-                                                       throw e;
-                                               }
+       /**
+        * This function parses the set of rules from a standard stylesheet
+        *
+        * @param array cssRules: the array of rules of a stylesheet
+        * @return void
+        */
+       Parser.prototype.parseRules = function (cssRules) {
+               for (var rule = 0, n = cssRules.length; rule < n; rule++) {
+                       // Style rule
+                       if (cssRules[rule].selectorText) {
+                               this.parseSelectorText(cssRules[rule].selectorText);
+                       } else {
+                               // Import rule
+                               try {
+                                       if (cssRules[rule].styleSheet && cssRules[rule].styleSheet.cssRules) {
+                                                       this.parseRules(cssRules[rule].styleSheet.cssRules);
                                        }
-                                               // Media rule
-                                       if (cssRules[rule].cssRules) {
-                                               this.parseRules(cssRules[rule].cssRules);
+                               } catch (e) {
+                                       if (/Security/i.test(e)) {
+                                               // If this is a security error, silently log the error and continue parsing
+                                               this.editor.appendToLog('HTMLArea.CSS.Parser', 'parseRules', 'A security error occurred. Make sure all stylesheets are accessed from the same domain/subdomain and using the same protocol as the current script.', 'error');
+                                       } else {
+                                               throw e;
                                        }
                                }
+                               // Media rule
+                               if (cssRules[rule].cssRules) {
+                                       this.parseRules(cssRules[rule].cssRules);
+                               }
                        }
-               },
+               }
+       };
 
-               /**
-                * This function parses the set of rules from an IE stylesheet
-                *
-                * @param       array           cssRules: the array of rules of a stylesheet
-                * @return      void
-                */
-               parseIeRules: function (cssRules) {
-                       for (var rule = 0, n = cssRules.length; rule < n; rule++) {
-                                       // Import rule
-                               if (cssRules[rule].imports) {
-                                       this.parseIeRules(cssRules[rule].imports);
-                               }
-                                       // Style rule
-                               if (cssRules[rule].rules) {
-                                       this.parseRules(cssRules[rule].rules);
-                               }
+       /**
+        * This function parses the set of rules from an IE stylesheet
+        *
+        * @param array cssRules: the array of rules of a stylesheet
+        * @return void
+        */
+       Parser.prototype.parseIeRules = function (cssRules) {
+               for (var rule = 0, n = cssRules.length; rule < n; rule++) {
+                               // Import rule
+                       if (cssRules[rule].imports) {
+                               this.parseIeRules(cssRules[rule].imports);
+                       }
+                               // Style rule
+                       if (cssRules[rule].rules) {
+                               this.parseRules(cssRules[rule].rules);
                        }
-               },
+               }
+       };
 
-               /**
-                * This function parses a selector rule
-                *
-                * @param       string          selectorText: the text of the rule to parsed
-                * @return      void
-                */
-               parseSelectorText: function (selectorText) {
-                       var cssElements = [],
-                               cssElement = [],
-                               nodeName, className,
-                               pattern = /(\S*)\.(\S+)/;
-                       if (selectorText.search(/:+/) == -1) {
-                                       // Split equal styles
-                               cssElements = selectorText.split(',');
-                               for (var k = 0, n = cssElements.length; k < n; k++) {
-                                               // Match all classes (<element name (optional)>.<class name>) in selector rule
-                                       var s = cssElements[k], index;
-                                       while ((index = s.search(pattern)) > -1) {
-                                               var match = pattern.exec(s.substring(index));
-                                               s = s.substring(index+match[0].length);
-                                               nodeName = (match[1] && (match[1] != '*')) ? match[1].toLowerCase().trim() : 'all';
-                                               className = match[2];
-                                               if (className && !HTMLArea.reservedClassNames.test(className)) {
-                                                       if (((nodeName != 'all') && (!this.tags || !this.tags[nodeName]))
-                                                               || ((nodeName == 'all') && (!this.tags || !this.tags[nodeName]) && this.showTagFreeClasses)
-                                                               || (this.tags && this.tags[nodeName] && this.tags[nodeName].allowedClasses && this.tags[nodeName].allowedClasses.test(className))) {
-                                                               if (!this.parsedClasses[nodeName]) {
-                                                                       this.parsedClasses[nodeName] = {};
-                                                               }
-                                                               cssName = className;
-                                                               if (HTMLArea.classesLabels && HTMLArea.classesLabels[className]) {
-                                                                       cssName = this.prefixLabelWithClassName ? (className + ' - ' + HTMLArea.classesLabels[className]) : HTMLArea.classesLabels[className];
-                                                                       cssName = this.postfixLabelWithClassName ? (cssName + ' - ' + className) : cssName;
-                                                               }
-                                                               this.parsedClasses[nodeName][className] = cssName;
+       /**
+        * This function parses a selector rule
+        *
+        * @param string selectorText: the text of the rule to parsed
+        * @return void
+        */
+       Parser.prototype.parseSelectorText = function (selectorText) {
+               var cssElements = [],
+                       cssElement = [],
+                       nodeName, className,
+                       pattern = /(\S*)\.(\S+)/;
+               if (selectorText.search(/:+/) == -1) {
+                               // Split equal styles
+                       cssElements = selectorText.split(',');
+                       for (var k = 0, n = cssElements.length; k < n; k++) {
+                                       // Match all classes (<element name (optional)>.<class name>) in selector rule
+                               var s = cssElements[k], index;
+                               while ((index = s.search(pattern)) > -1) {
+                                       var match = pattern.exec(s.substring(index));
+                                       s = s.substring(index+match[0].length);
+                                       nodeName = (match[1] && (match[1] != '*')) ? match[1].toLowerCase().trim() : 'all';
+                                       className = match[2];
+                                       if (className && !HTMLArea.reservedClassNames.test(className)) {
+                                               if (((nodeName != 'all') && (!this.tags || !this.tags[nodeName]))
+                                                       || ((nodeName == 'all') && (!this.tags || !this.tags[nodeName]) && this.showTagFreeClasses)
+                                                       || (this.tags && this.tags[nodeName] && this.tags[nodeName].allowedClasses && this.tags[nodeName].allowedClasses.test(className))) {
+                                                       if (!this.parsedClasses[nodeName]) {
+                                                               this.parsedClasses[nodeName] = {};
                                                        }
+                                                       cssName = className;
+                                                       if (HTMLArea.classesLabels && HTMLArea.classesLabels[className]) {
+                                                               cssName = this.prefixLabelWithClassName ? (className + ' - ' + HTMLArea.classesLabels[className]) : HTMLArea.classesLabels[className];
+                                                               cssName = this.postfixLabelWithClassName ? (cssName + ' - ' + className) : cssName;
+                                                       }
+                                                       this.parsedClasses[nodeName][className] = cssName;
                                                }
                                        }
                                }
                        }
-               },
+               }
+       };
 
-               /**
-                * This function filters the class selectors allowed for each nodeName
-                *
-                * @return      void
-                */
-               filterAllowedClasses: function() {
-                       var nodeName, cssClass;
-                       for (nodeName in this.tags) {
-                               var allowedClasses = {};
-                               // Get classes allowed for all tags
-                               if (nodeName !== 'all' && typeof this.parsedClasses['all'] !== 'undefined') {
-                                       if (this.tags && this.tags[nodeName] && this.tags[nodeName].allowedClasses) {
-                                               var allowed = this.tags[nodeName].allowedClasses;
-                                               for (cssClass in this.parsedClasses['all']) {
-                                                       if (allowed.test(cssClass)) {
-                                                               allowedClasses[cssClass] = this.parsedClasses['all'][cssClass];
-                                                       }
+       /**
+        * This function filters the class selectors allowed for each nodeName
+        *
+        * @return void
+        */
+       Parser.prototype.filterAllowedClasses = function() {
+               var nodeName, cssClass;
+               for (nodeName in this.tags) {
+                       var allowedClasses = {};
+                       // Get classes allowed for all tags
+                       if (nodeName !== 'all' && typeof this.parsedClasses['all'] !== 'undefined') {
+                               if (this.tags && this.tags[nodeName] && this.tags[nodeName].allowedClasses) {
+                                       var allowed = this.tags[nodeName].allowedClasses;
+                                       for (cssClass in this.parsedClasses['all']) {
+                                               if (allowed.test(cssClass)) {
+                                                       allowedClasses[cssClass] = this.parsedClasses['all'][cssClass];
                                                }
-                                       } else {
-                                               allowedClasses = this.parsedClasses['all'];
                                        }
+                               } else {
+                                       allowedClasses = this.parsedClasses['all'];
                                }
-                               // Merge classes allowed for nodeName
-                               if (typeof this.parsedClasses[nodeName] !== 'undefined') {
-                                       if (this.tags && this.tags[nodeName] && this.tags[nodeName].allowedClasses) {
-                                               var allowed = this.tags[nodeName].allowedClasses;
-                                               for (cssClass in this.parsedClasses[nodeName]) {
-                                                       if (allowed.test(cssClass)) {
-                                                               allowedClasses[cssClass] = this.parsedClasses[nodeName][cssClass];
-                                                       }
-                                               }
-                                       } else {
-                                               for (cssClass in this.parsedClasses[nodeName]) {
+                       }
+                       // Merge classes allowed for nodeName
+                       if (typeof this.parsedClasses[nodeName] !== 'undefined') {
+                               if (this.tags && this.tags[nodeName] && this.tags[nodeName].allowedClasses) {
+                                       var allowed = this.tags[nodeName].allowedClasses;
+                                       for (cssClass in this.parsedClasses[nodeName]) {
+                                               if (allowed.test(cssClass)) {
                                                        allowedClasses[cssClass] = this.parsedClasses[nodeName][cssClass];
                                                }
                                        }
+                               } else {
+                                       for (cssClass in this.parsedClasses[nodeName]) {
+                                               allowedClasses[cssClass] = this.parsedClasses[nodeName][cssClass];
+                                       }
                                }
-                               this.parsedClasses[nodeName] = allowedClasses;
                        }
-                       // If showTagFreeClasses is set and there is no allowedClasses clause on a tag, merge classes allowed for all tags
-                       if (this.showTagFreeClasses && typeof this.parsedClasses['all'] !== 'undefined') {
-                               for (nodeName in this.parsedClasses) {
-                                       if (nodeName !== 'all' && !this.tags[nodeName]) {
-                                               for (cssClass in this.parsedClasses['all']) {
-                                                       this.parsedClasses[nodeName][cssClass] = this.parsedClasses['all'][cssClass];
-                                               }
+                       this.parsedClasses[nodeName] = allowedClasses;
+               }
+               // If showTagFreeClasses is set and there is no allowedClasses clause on a tag, merge classes allowed for all tags
+               if (this.showTagFreeClasses && typeof this.parsedClasses['all'] !== 'undefined') {
+                       for (nodeName in this.parsedClasses) {
+                               if (nodeName !== 'all' && !this.tags[nodeName]) {
+                                       for (cssClass in this.parsedClasses['all']) {
+                                               this.parsedClasses[nodeName][cssClass] = this.parsedClasses['all'][cssClass];
                                        }
                                }
                        }
-               },
+               }
+       };
 
-               /**
-                * This function sorts the class selectors for each nodeName
-                *
-                * @return void
-                */
-               sort: function() {
-                       var nodeName, cssClass, i, n, x, y;
-                       for (nodeName in this.parsedClasses) {
-                               var value = this.parsedClasses[nodeName];
-                               var classes = [];
-                               var sortedClasses = {};
-                               // Collect keys
-                               for (cssClass in value) {
-                                       classes.push(cssClass);
-                               }
-                               function compare(a, b) {
-                                       x = value[a];
-                                       y = value[b];
-                                       return ((x < y) ? -1 : ((x > y) ? 1 : 0));
-                               }
-                               // Sort keys by comparing texts
-                               classes = classes.sort(compare);
-                               for (i = 0, n = classes.length; i < n; ++i) {
-                                       sortedClasses[classes[i]] = value[classes[i]];
-                               }
-                               this.parsedClasses[nodeName] = sortedClasses;
+       /**
+        * This function sorts the class selectors for each nodeName
+        *
+        * @return void
+        */
+       Parser.prototype.sort = function() {
+               var nodeName, cssClass, i, n, x, y;
+               for (nodeName in this.parsedClasses) {
+                       var value = this.parsedClasses[nodeName];
+                       var classes = [];
+                       var sortedClasses = {};
+                       // Collect keys
+                       for (cssClass in value) {
+                               classes.push(cssClass);
+                       }
+                       function compare(a, b) {
+                               x = value[a];
+                               y = value[b];
+                               return ((x < y) ? -1 : ((x > y) ? 1 : 0));
+                       }
+                       // Sort keys by comparing texts
+                       classes = classes.sort(compare);
+                       for (i = 0, n = classes.length; i < n; ++i) {
+                               sortedClasses[classes[i]] = value[classes[i]];
                        }
+                       this.parsedClasses[nodeName] = sortedClasses;
                }
-       });
+       };
 
        return Parser;
 
index 519c1a8..6345a84 100644 (file)
@@ -26,556 +26,569 @@ define('TYPO3/CMS/Rtehtmlarea/HTMLArea/Editor/Editor',
        'TYPO3/CMS/Rtehtmlarea/HTMLArea/Editor/Framework'],
        function (UserAgent, Util, Ajax, Dom, Event, Selection, BookMark, Node, Typo3, Framework) {
 
-       var Editor = Ext.extend(Ext.util.Observable, {
-
-               /**
-                * Editor constructor
-                */
-               constructor: function (config) {
-                       Editor.superclass.constructor.call(this, {});
-                       // Save the config
-                       this.config = config;
-                       // Establish references to this editor
-                       this.editorId = this.config.editorId;
-                       RTEarea[this.editorId].editor = this;
-                       // Get textarea size and wizard context
-                       this.textArea = document.getElementById(this.config.id);
-                       var computedStyle = window.getComputedStyle ? window.getComputedStyle(this.textArea) : null;
-                       this.textAreaInitialSize = {
-                               width: this.config.RTEWidthOverride ? this.config.RTEWidthOverride : (this.textArea.style.width ? this.textArea.style.width : (computedStyle ? computedStyle.width : 0)),
-                               height: this.config.fullScreen ? Typo3.getWindowSize().height - 25 : (this.textArea.style.height ? this.textArea.style.height : (computedStyle ? computedStyle.height : 0)),
-                               wizardsWidth: 0
-                       };
-                       // TYPO3 Inline elements and tabs
-                       this.nestedParentElements = {
-                               all: this.config.tceformsNested,
-                               sorted: Typo3.simplifyNested(this.config.tceformsNested)
-                       };
-                       this.isNested = this.nestedParentElements.sorted.length > 0;
-                       // If in BE, get width of wizards
-                       if (document.getElementById('typo3-docheader') && !this.config.fullScreen) {
-                               this.wizards = this.textArea.parentNode.parentNode.nextSibling;
-                               if (this.wizards && this.wizards.nodeType === Dom.ELEMENT_NODE) {
-                                       if (!this.isNested || Typo3.allElementsAreDisplayed(this.nestedParentElements.sorted)) {
-                                               this.textAreaInitialSize.wizardsWidth = this.wizards.offsetWidth;
-                                       } else {
-                                               // Clone the array of nested tabs and inline levels instead of using a reference as HTMLArea.util.TYPO3.accessParentElements will modify the array
-                                               var parentElements = [].concat(this.nestedParentElements.sorted);
-                                               // Walk through all nested tabs and inline levels to get correct size
-                                               this.textAreaInitialSize.wizardsWidth = Typo3.accessParentElements(parentElements, 'args[0].offsetWidth', [this.wizards]);
-                                       }
-                                       // Hide the wizards so that they do not move around while the editor framework is being sized
-                                       this.wizards.style.display = 'none';
+       /**
+        * Editor constructor method
+        *
+        * @param object config: editor configuration object
+        */
+       var Editor = function (config) {
+               // Save the config
+               this.config = config;
+               // Establish references to this editor
+               this.editorId = this.config.editorId;
+               RTEarea[this.editorId].editor = this;
+               // Get textarea size and wizard context
+               this.textArea = document.getElementById(this.config.id);
+               var computedStyle = window.getComputedStyle ? window.getComputedStyle(this.textArea) : null;
+               this.textAreaInitialSize = {
+                       width: this.config.RTEWidthOverride ? this.config.RTEWidthOverride : (this.textArea.style.width ? this.textArea.style.width : (computedStyle ? computedStyle.width : 0)),
+                       height: this.config.fullScreen ? Typo3.getWindowSize().height - 25 : (this.textArea.style.height ? this.textArea.style.height : (computedStyle ? computedStyle.height : 0)),
+                       wizardsWidth: 0
+               };
+               // TYPO3 Inline elements and tabs
+               this.nestedParentElements = {
+                       all: this.config.tceformsNested,
+                       sorted: Typo3.simplifyNested(this.config.tceformsNested)
+               };
+               this.isNested = this.nestedParentElements.sorted.length > 0;
+               // If in BE, get width of wizards
+               if (document.getElementById('typo3-docheader') && !this.config.fullScreen) {
+                       this.wizards = this.textArea.parentNode.parentNode.nextSibling;
+                       if (this.wizards && this.wizards.nodeType === Dom.ELEMENT_NODE) {
+                               if (!this.isNested || Typo3.allElementsAreDisplayed(this.nestedParentElements.sorted)) {
+                                       this.textAreaInitialSize.wizardsWidth = this.wizards.offsetWidth;
+                               } else {
+                                       // Clone the array of nested tabs and inline levels instead of using a reference as HTMLArea.util.TYPO3.accessParentElements will modify the array
+                                       var parentElements = [].concat(this.nestedParentElements.sorted);
+                                       // Walk through all nested tabs and inline levels to get correct size
+                                       this.textAreaInitialSize.wizardsWidth = Typo3.accessParentElements(parentElements, 'args[0].offsetWidth', [this.wizards]);
                                }
+                               // Hide the wizards so that they do not move around while the editor framework is being sized
+                               this.wizards.style.display = 'none';
                        }
-                       // Plugins register
-                       this.plugins = {};
-                       // Register the plugins included in the configuration
-                       for (var plugin in this.config.plugin) {
-                               if (this.config.plugin[plugin]) {
-                                       this.registerPlugin(plugin);
-                               }
+               }
+               // Plugins register
+               this.plugins = {};
+               // Register the plugins included in the configuration
+               for (var plugin in this.config.plugin) {
+                       if (this.config.plugin[plugin]) {
+                               this.registerPlugin(plugin);
                        }
-                       // Create Ajax object
-                       this.ajax = new Ajax({
-                               editor: this
-                       });
-                       // Initialize keyboard input inhibit flag
-                       this.inhibitKeyboardInput = false;
-               },
-               /*
+               }
+               // Create Ajax object
+               this.ajax = new Ajax({
+                       editor: this
+               });
+               // Initialize keyboard input inhibit flag
+               this.inhibitKeyboardInput = false;
+
+               /**
                 * Flag set to true when the editor initialization has completed
                 */
-               ready: false,
-               /*
+               this.ready = false;
+
+               /**
                 * The current mode of the editor: 'wysiwyg' or 'textmode'
                 */
-               mode: 'textmode',
-               /*
-                * Determine whether the editor document is currently contentEditable
-                *
-                * @return      boolean         true, if the document is contentEditable
-                */
-               isEditable: function () {
-                       return UserAgent.isIE ? this.document.body.contentEditable : (this.document.designMode === 'on');
-               },
-               /*
-                * The selection object
-                */
-               selection: null,
-               getSelection: function () {
-                       if (!this.selection) {
-                               this.selection = new Selection({
-                                       editor: this
-                               });
-                       }
-                       return this.selection;
-               },
-               /*
-                * The bookmark object
-                */
-               bookMark: null,
-               getBookMark: function () {
-                       if (!this.bookMark) {
-                               this.bookMark = new BookMark({
-                                       editor: this
-                               });
-                       }
-                       return this.bookMark;
-               },
-               /*
-                * The DOM node object
+               this.mode = 'textmode';
+
+               /**
+                * The Selection object
                 */
-               domNode: null,
-               getDomNode: function () {
-                       if (!this.domNode) {
-                               this.domNode = new Node({
-                                       editor: this
-                               });
-                       }
-                       return this.domNode;
-               },
+               this.selection = null;
 
                /**
-                * Generate the editor framework
+                * The BookMark object
                 */
-               generate: function () {
-                       if (this.allPluginsRegistered()) {
-                               this.createFramework();
-                       } else {
-                               var self = this;
-                               window.setTimeout(function () {
-                                       self.generate();
-                               }, 50);
-                       }
-               },
+               this.bookMark = null;
 
                /**
-                * Create the htmlArea framework
+                * The DomNode object
                 */
-               createFramework: function () {
-                       // Create the editor framework
-                       this.htmlArea = new Framework({
-                               id: this.editorId + '-htmlArea',
-                               layout: 'anchor',
-                               baseCls: 'htmlarea',
-                               editorId: this.editorId,
-                               textArea: this.textArea,
-                               textAreaInitialSize: this.textAreaInitialSize,
-                               fullScreen: this.config.fullScreen,
-                               resizable: this.config.resizable,
-                               maxHeight: this.config.maxHeight,
-                               isNested: this.isNested,
-                               nestedParentElements: this.nestedParentElements,
-                               // The toolbar
-                               tbar: {
-                                       xtype: 'htmlareatoolbar',
-                                       id: this.editorId + '-toolbar',
-                                       anchor: '100%',
-                                       layout: 'form',
-                                       cls: 'toolbar',
+               this.domNode = null;
+       };
+
+       /**
+        * Determine whether the editor document is currently contentEditable
+        *
+        * @return      boolean         true, if the document is contentEditable
+        */
+       Editor.prototype.isEditable = function () {
+               return UserAgent.isIE ? this.document.body.contentEditable : (this.document.designMode === 'on');
+       };
+
+       /**
+        * The selection object
+        */
+       Editor.prototype.getSelection = function () {
+               if (!this.selection) {
+                       this.selection = new Selection({
+                               editor: this
+                       });
+               }
+               return this.selection;
+       };
+
+       /**
+        * The bookmark object
+        */
+       Editor.prototype.getBookMark = function () {
+               if (!this.bookMark) {
+                       this.bookMark = new BookMark({
+                               editor: this
+                       });
+               }
+               return this.bookMark;
+       };
+
+       /**
+        * The DOM node object
+        */
+       Editor.prototype.getDomNode = function () {
+               if (!this.domNode) {
+                       this.domNode = new Node({
+                               editor: this
+                       });
+               }
+               return this.domNode;
+       };
+
+       /**
+        * Generate the editor framework
+        */
+       Editor.prototype.generate = function () {
+               if (this.allPluginsRegistered()) {
+                       this.createFramework();
+               } else {
+                       var self = this;
+                       window.setTimeout(function () {
+                               self.generate();
+                       }, 50);
+               }
+       };
+
+       /**
+        * Create the htmlArea framework
+        */
+       Editor.prototype.createFramework = function () {
+               // Create the editor framework
+               this.htmlArea = new Framework({
+                       id: this.editorId + '-htmlArea',
+                       layout: 'anchor',
+                       baseCls: 'htmlarea',
+                       editorId: this.editorId,
+                       textArea: this.textArea,
+                       textAreaInitialSize: this.textAreaInitialSize,
+                       fullScreen: this.config.fullScreen,
+                       resizable: this.config.resizable,
+                       maxHeight: this.config.maxHeight,
+                       isNested: this.isNested,
+                       nestedParentElements: this.nestedParentElements,
+                       // The toolbar
+                       tbar: {
+                               xtype: 'htmlareatoolbar',
+                               id: this.editorId + '-toolbar',
+                               anchor: '100%',
+                               layout: 'form',
+                               cls: 'toolbar',
+                               editorId: this.editorId
+                       },
+                       items: [{
+                                       // The iframe
+                                       xtype: 'htmlareaiframe',
+                                       itemId: 'iframe',
+                                       width: (this.textAreaInitialSize.width.indexOf('%') === -1) ? parseInt(this.textAreaInitialSize.width) : 300,
+                                       height: parseInt(this.textAreaInitialSize.height),
+                                       autoEl: {
+                                               id: this.editorId + '-iframe',
+                                               tag: 'iframe',
+                                               cls: 'editorIframe',
+                                               src: UserAgent.isGecko ? 'javascript:void(0);' : (UserAgent.isWebKit ? 'javascript: \'' + Util.htmlEncode(this.config.documentType + this.config.blankDocument) + '\'' : HTMLArea.editorUrl + 'Resources/Public/Html/blank.html')
+                                       },
+                                       isNested: this.isNested,
+                                       nestedParentElements: this.nestedParentElements,
                                        editorId: this.editorId
-                               },
-                               items: [{
-                                               // The iframe
-                                               xtype: 'htmlareaiframe',
-                                               itemId: 'iframe',
-                                               width: (this.textAreaInitialSize.width.indexOf('%') === -1) ? parseInt(this.textAreaInitialSize.width) : 300,
-                                               height: parseInt(this.textAreaInitialSize.height),
-                                               autoEl: {
-                                                       id: this.editorId + '-iframe',
-                                                       tag: 'iframe',
-                                                       cls: 'editorIframe',
-                                                       src: UserAgent.isGecko ? 'javascript:void(0);' : (UserAgent.isWebKit ? 'javascript: \'' + Util.htmlEncode(this.config.documentType + this.config.blankDocument) + '\'' : HTMLArea.editorUrl + 'Resources/Public/Html/blank.html')
+                               },{
+                                       // Box container for the textarea
+                                       xtype: 'box',
+                                       itemId: 'textAreaContainer',
+                                       anchor: '100%',
+                                       width: (this.textAreaInitialSize.width.indexOf('%') === -1) ? parseInt(this.textAreaInitialSize.width) : 300,
+                                       // Let the framework swallow the textarea and throw it back
+                                       listeners: {
+                                               afterrender: {
+                                                       fn: function (textAreaContainer) {
+                                                               this.originalParent = this.textArea.parentNode;
+                                                               textAreaContainer.getEl().appendChild(this.textArea);
+                                                       },
+                                                       single: true,
+                                                       scope: this
                                                },
-                                               isNested: this.isNested,
-                                               nestedParentElements: this.nestedParentElements,
-                                               editorId: this.editorId
-                                       },{
-                                               // Box container for the textarea
-                                               xtype: 'box',
-                                               itemId: 'textAreaContainer',
-                                               anchor: '100%',
-                                               width: (this.textAreaInitialSize.width.indexOf('%') === -1) ? parseInt(this.textAreaInitialSize.width) : 300,
-                                               // Let the framework swallow the textarea and throw it back
-                                               listeners: {
-                                                       afterrender: {
-                                                               fn: function (textAreaContainer) {
-                                                                       this.originalParent = this.textArea.parentNode;
-                                                                       textAreaContainer.getEl().appendChild(this.textArea);
-                                                               },
-                                                               single: true,
-                                                               scope: this
+                                               beforedestroy: {
+                                                       fn: function (textAreaContainer) {
+                                                               this.originalParent.appendChild(this.textArea);
+                                                               return true;
                                                        },
-                                                       beforedestroy: {
-                                                               fn: function (textAreaContainer) {
-                                                                       this.originalParent.appendChild(this.textArea);
-                                                                       return true;
-                                                               },
-                                                               single: true,
-                                                               scope: this
-                                                       }
+                                                       single: true,
+                                                       scope: this
                                                }
                                        }
-                               ],
-                               // The status bar
-                               bbar: {
-                                       xtype: 'htmlareastatusbar',
-                                       anchor: '100%',
-                                       cls: 'statusBar',
-                                       editorId: this.editorId
                                }
-                       });
-                       // Set some references
-                       this.toolbar = this.htmlArea.getTopToolbar();
-                       this.statusBar = this.htmlArea.getBottomToolbar();
-                       this.iframe = this.htmlArea.getComponent('iframe');
-                       this.textAreaContainer = this.htmlArea.getComponent('textAreaContainer');
-                       // Get triggered when the framework becomes ready
-                       var self = this;
-                       Event.one(this.htmlArea, 'HTMLAreaEventFrameworkReady', function (event) { Event.stopEvent(event); self.onFrameworkReady(); return false; });
-               },
+                       ],
+                       // The status bar
+                       bbar: {
+                               xtype: 'htmlareastatusbar',
+                               anchor: '100%',
+                               cls: 'statusBar',
+                               editorId: this.editorId
+                       }
+               });
+               // Set some references
+               this.toolbar = this.htmlArea.getTopToolbar();
+               this.statusBar = this.htmlArea.getBottomToolbar();
+               this.iframe = this.htmlArea.getComponent('iframe');
+               this.textAreaContainer = this.htmlArea.getComponent('textAreaContainer');
+               // Get triggered when the framework becomes ready
+               var self = this;
+               Event.one(this.htmlArea, 'HTMLAreaEventFrameworkReady', function (event) { Event.stopEvent(event); self.onFrameworkReady(); return false; });
+       };
 
-               /**
-                * Initialize the editor
-                */
-               onFrameworkReady: function () {
-                       // Initialize editor mode
-                       this.setMode('wysiwyg');
-                       // Create the selection object
-                       this.getSelection();
-                       // Create the bookmark object
-                       this.getBookMark();
-                       // Create the DOM node object
-                       this.getDomNode();
-                       // Initiate events listening
-                       this.initEventsListening();
-                       // Load the classes configuration
-                       this.getClassesConfiguration();
-               },
-               
-               /**
-                * Get the classes configuration
-                * This is required before plugins are generated
-                *
-                * @return      void
-                */
-               getClassesConfiguration: function () {
-                       if (this.config.classesUrl && typeof HTMLArea.classesLabels === 'undefined') {
-                               this.ajax.getJavascriptFile(this.config.classesUrl, function (options, success, response) {
-                                       if (success) {
-                                               try {
-                                                       if (typeof HTMLArea.classesLabels === 'undefined') {
-                                                               eval(response.responseText);
-                                                       }
-                                               } catch(e) {
-                                                       this.appendToLog('HTMLArea.Editor', 'getClassesConfiguration', 'Error evaluating contents of Javascript file: ' + this.config.classesUrl, 'error');
+       /**
+        * Initialize the editor
+        */
+       Editor.prototype.onFrameworkReady = function () {
+               // Initialize editor mode
+               this.setMode('wysiwyg');
+               // Create the selection object
+               this.getSelection();
+               // Create the bookmark object
+               this.getBookMark();
+               // Create the DOM node object
+               this.getDomNode();
+               // Initiate events listening
+               this.initEventsListening();
+               // Load the classes configuration
+               this.getClassesConfiguration();
+       };
+
+       /**
+        * Get the classes configuration
+        * This is required before plugins are generated
+        *
+        * @return void
+        */
+       Editor.prototype.getClassesConfiguration = function () {
+               if (this.config.classesUrl && typeof HTMLArea.classesLabels === 'undefined') {
+                       this.ajax.getJavascriptFile(this.config.classesUrl, function (options, success, response) {
+                               if (success) {
+                                       try {
+                                               if (typeof HTMLArea.classesLabels === 'undefined') {
+                                                       eval(response.responseText);
                                                }
+                                       } catch(e) {
+                                               this.appendToLog('HTMLArea.Editor', 'getClassesConfiguration', 'Error evaluating contents of Javascript file: ' + this.config.classesUrl, 'error');
                                        }
-                                       this.initializeEditor();
-                               }, this);
-                       } else {
+                               }
                                this.initializeEditor();
-                       }
-               },
+                       }, this);
+               } else {
+                       this.initializeEditor();
+               }
+       };
 
+       /**
+        * Complete editor initialization
+        *
+        * @return void
+        */
+       Editor.prototype.initializeEditor = function () {
+               // Generate plugins
+               this.generatePlugins();
+               // Make the editor visible
+               this.show();
+               // Make the wizards visible again
+               if (this.wizards && this.wizards.nodeType === Dom.ELEMENT_NODE) {
+                       this.wizards.style.display = '';
+               }
+               // Focus on the first editor that is not hidden
+               for (var editorId in RTEarea) {
+                       var RTE = RTEarea[editorId];
+                       if (typeof RTE.editor !== 'object' || RTE.editor === null || (RTE.editor.isNested && !Typo3.allElementsAreDisplayed(RTE.editor.nestedParentElements.sorted))) {
+                               continue;
+                       } else {
+                               RTE.editor.focus();
+                               break;
+                       }
+               }
+               this.ready = true;
                /**
-                * Complete editor initialization
-                *
-                * @return void
+                * @event EditorReady
+                * Fires when initialization of the editor is complete
                 */
-               initializeEditor: function () {
-                       // Generate plugins
-                       this.generatePlugins();
-                       // Make the editor visible
-                       this.show();
-                       // Make the wizards visible again
-                       if (this.wizards && this.wizards.nodeType === Dom.ELEMENT_NODE) {
-                               this.wizards.style.display = '';
-                       }
-                       // Focus on the first editor that is not hidden
-                       for (var editorId in RTEarea) {
-                               var RTE = RTEarea[editorId];
-                               if (typeof RTE.editor !== 'object' || RTE.editor === null || (RTE.editor.isNested && !Typo3.allElementsAreDisplayed(RTE.editor.nestedParentElements.sorted))) {
-                                       continue;
-                               } else {
-                                       RTE.editor.focus();
+               Event.trigger(this, 'HtmlAreaEventEditorReady');
+               this.appendToLog('HTMLArea.Editor', 'onFrameworkReady', 'Editor ready.', 'info');
+       };
+
+       /**
+        * Set editor mode
+        *
+        * @param string mode: 'textmode' or 'wysiwyg'
+        * @return void
+        */
+       Editor.prototype.setMode = function (mode) {
+               switch (mode) {
+                       case 'textmode':
+                               this.textArea.value = this.getHTML();
+                               this.iframe.setDesignMode(false);
+                               this.iframe.hide();
+                               this.textAreaContainer.show();
+                               this.mode = mode;
+                               break;
+                       case 'wysiwyg':
+                               try {
+                                       this.document.body.innerHTML = this.getHTML();
+                               } catch(e) {
+                                       this.appendToLog('HTMLArea.Editor', 'setMode', 'The HTML document is not well-formed.', 'warn');
+                                       TYPO3.Dialog.ErrorDialog({
+                                               title: 'htmlArea RTE',
+                                               msg: HTMLArea.localize('HTML-document-not-well-formed')
+                                       });
                                        break;
                                }
-                       }
-                       this.ready = true;
-                       /**
-                        * @event EditorReady
-                        * Fires when initialization of the editor is complete
-                        */
-                       Event.trigger(this, 'HtmlAreaEventEditorReady');
-                       this.appendToLog('HTMLArea.Editor', 'onFrameworkReady', 'Editor ready.', 'info');
-               },
-       
+                               this.textAreaContainer.hide();
+                               this.iframe.show();
+                               this.iframe.setDesignMode(true);
+                               this.mode = mode;
+                               break;
+               }
                /**
-                * Set editor mode
-                *
-                * @param string mode: 'textmode' or 'wysiwyg'
-                * @return void
+                * @event HTMLAreaEventModeChange
+                * Fires when the editor changes mode
                 */
-               setMode: function (mode) {
-                       switch (mode) {
-                               case 'textmode':
-                                       this.textArea.value = this.getHTML();
-                                       this.iframe.setDesignMode(false);
-                                       this.iframe.hide();
-                                       this.textAreaContainer.show();
-                                       this.mode = mode;
-                                       break;
-                               case 'wysiwyg':
-                                       try {
-                                               this.document.body.innerHTML = this.getHTML();
-                                       } catch(e) {
-                                               this.appendToLog('HTMLArea.Editor', 'setMode', 'The HTML document is not well-formed.', 'warn');
-                                               TYPO3.Dialog.ErrorDialog({
-                                                       title: 'htmlArea RTE',
-                                                       msg: HTMLArea.localize('HTML-document-not-well-formed')
-                                               });
-                                               break;
-                                       }
-                                       this.textAreaContainer.hide();
-                                       this.iframe.show();
-                                       this.iframe.setDesignMode(true);
-                                       this.mode = mode;
-                                       break;
-                       }
-                       /**
-                        * @event HTMLAreaEventModeChange
-                        * Fires when the editor changes mode
-                        */
-                       Event.trigger(this, 'HTMLAreaEventModeChange', [this.mode]);
-                       this.focus();
-                       for (var pluginId in this.plugins) {
-                               this.getPlugin(pluginId).onMode(this.mode);
-                       }
-               },
+               Event.trigger(this, 'HTMLAreaEventModeChange', [this.mode]);
+               this.focus();
+               for (var pluginId in this.plugins) {
+                       this.getPlugin(pluginId).onMode(this.mode);
+               }
+       };
 
-               /**
-                * Get current editor mode
-                */
-               getMode: function () {
-                       return this.mode;
-               },
+       /**
+        * Get current editor mode
+        */
+       Editor.prototype.getMode = function () {
+               return this.mode;
+       };
 
-               /**
-                * Retrieve the HTML
-                * In the case of the wysiwyg mode, the html content is rendered from the DOM tree
-                *
-                * @return string the textual html content from the current editing mode
-                */
-               getHTML: function () {
-                       switch (this.mode) {
-                               case 'wysiwyg':
-                                       return this.iframe.getHTML();
-                               case 'textmode':
-                                       // Collapse repeated spaces non-editable in wysiwyg
-                                       // Replace leading and trailing spaces non-editable in wysiwyg
-                                       return this.textArea.value.
-                                               replace(/[\x20]+/g, '\x20').
-                                               replace(/^\x20/g, '&nbsp;').
-                                               replace(/\x20$/g, '&nbsp;');
-                               default:
-                                       return '';
-                       }
-               },
+       /**
+        * Retrieve the HTML
+        * In the case of the wysiwyg mode, the html content is rendered from the DOM tree
+        *
+        * @return string the textual html content from the current editing mode
+        */
+       Editor.prototype.getHTML = function () {
+               switch (this.mode) {
+                       case 'wysiwyg':
+                               return this.iframe.getHTML();
+                       case 'textmode':
+                               // Collapse repeated spaces non-editable in wysiwyg
+                               // Replace leading and trailing spaces non-editable in wysiwyg
+                               return this.textArea.value.
+                                       replace(/[\x20]+/g, '\x20').
+                                       replace(/^\x20/g, '&nbsp;').
+                                       replace(/\x20$/g, '&nbsp;');
+                       default:
+                               return '';
+               }
+       };
 
-               /**
-                * Retrieve raw HTML
-                *
-                * @return      string  the textual html content from the current editing mode
-                */
-               getInnerHTML: function () {
-                       switch (this.mode) {
-                               case 'wysiwyg':
-                                       return this.document.body.innerHTML;
-                               case 'textmode':
-                                       return this.textArea.value;
-                               default:
-                                       return '';
-                       }
-               },
+       /**
+        * Retrieve raw HTML
+        *
+        * @return string the textual html content from the current editing mode
+        */
+       Editor.prototype.getInnerHTML = function () {
+               switch (this.mode) {
+                       case 'wysiwyg':
+                               return this.document.body.innerHTML;
+                       case 'textmode':
+                               return this.textArea.value;
+                       default:
+                               return '';
+               }
+       };
 
-               /**
-                * Replace the html content
-                *
-                * @param       string          html: the textual html
-                *
-                * @return      void
-                */
-               setHTML: function (html) {
-                       switch (this.mode) {
-                               case 'wysiwyg':
-                                       this.document.body.innerHTML = html;
-                                       break;
-                               case 'textmode':
-                                       this.textArea.value = html;
-                                       break;
-                       }
-               },
+       /**
+        * Replace the html content
+        *
+        * @param string html: the textual html
+        * @return void
+        */
+       Editor.prototype.setHTML = function (html) {
+               switch (this.mode) {
+                       case 'wysiwyg':
+                               this.document.body.innerHTML = html;
+                               break;
+                       case 'textmode':
+                               this.textArea.value = html;
+                               break;
+               }
+       };
 
-               /**
-                * Require and instantiate the specified plugin and register it with the editor
-                *
-                * @param string plugin: the name of the plugin
-                * @return void
-                */
-               registerPlugin: function (pluginName) {
-                       var self = this;
-                       require(['TYPO3/CMS/Rtehtmlarea/Plugins/' + pluginName], function (Plugin) {
-                               var pluginInstance = new Plugin(self, pluginName);
-                               if (pluginInstance) {
-                                       var pluginInformation = pluginInstance.getPluginInformation();
-                                       pluginInformation.instance = pluginInstance;
-                                       self.plugins[pluginName] = pluginInformation;
-                               } else {
-                                       self.appendToLog('HTMLArea.Editor', 'registerPlugin', 'Could not register plugin ' + pluginName + '.', 'warn');
-                               }
-                       });
-               },
+       /**
+        * Require and instantiate the specified plugin and register it with the editor
+        *
+        * @param string plugin: the name of the plugin
+        * @return void
+        */
+       Editor.prototype.registerPlugin = function (pluginName) {
+               var self = this;
+               require(['TYPO3/CMS/Rtehtmlarea/Plugins/' + pluginName], function (Plugin) {
+                       var pluginInstance = new Plugin(self, pluginName);
+                       if (pluginInstance) {
+                               var pluginInformation = pluginInstance.getPluginInformation();
+                               pluginInformation.instance = pluginInstance;
+                               self.plugins[pluginName] = pluginInformation;
+                       } else {
+                               self.appendToLog('HTMLArea.Editor', 'registerPlugin', 'Could not register plugin ' + pluginName + '.', 'warn');
+                       }
+               });
+       };
 
-               /**
-                * Determine if all configured plugins are registered
-                *
-                * @return true if all configured plugins are registered
-                */
-               allPluginsRegistered: function () {
-                       for (var plugin in this.config.plugin) {
-                               if (this.config.plugin[plugin]) {
-                                       if (!this.plugins[plugin]) {
-                                               return false;
-                                       }
+       /**
+        * Determine if all configured plugins are registered
+        *
+        * @return true if all configured plugins are registered
+        */
+       Editor.prototype.allPluginsRegistered = function () {
+               for (var plugin in this.config.plugin) {
+                       if (this.config.plugin[plugin]) {
+                               if (!this.plugins[plugin]) {
+                                       return false;
                                }
                        }
-                       return true;
-               },
+               }
+               return true;
+       };
 
-               /**
-                * Generate registered plugins
-                */
-               generatePlugins: function () {
-                       for (var pluginId in this.plugins) {
-                               var plugin = this.getPlugin(pluginId);
-                               plugin.onGenerate();
-                       }
-               },
+       /**
+        * Generate registered plugins
+        */
+       Editor.prototype.generatePlugins = function () {
+               for (var pluginId in this.plugins) {
+                       var plugin = this.getPlugin(pluginId);
+                       plugin.onGenerate();
+               }
+       };
 
-               /**
-                * Get the instance of the specified plugin, if it exists
-                *
-                * @param       string          pluginName: the name of the plugin
-                * @return      object          the plugin instance or null
-                */
-               getPlugin: function(pluginName) {
-                       return (this.plugins[pluginName] ? this.plugins[pluginName].instance : null);
-               },
+       /**
+        * Get the instance of the specified plugin, if it exists
+        *
+        * @param string pluginName: the name of the plugin
+        * @return object the plugin instance or null
+        */
+       Editor.prototype.getPlugin = function(pluginName) {
+               return (this.plugins[pluginName] ? this.plugins[pluginName].instance : null);
+       };
 
-               /**
-                * Unregister the instance of the specified plugin
-                *
-                * @param       string          pluginName: the name of the plugin
-                * @return      void
-                */
-               unRegisterPlugin: function(pluginName) {
-                       delete this.plugins[pluginName].instance;
-                       delete this.plugins[pluginName];
-               },
+       /**
+        * Unregister the instance of the specified plugin
+        *
+        * @param string pluginName: the name of the plugin
+        * @return void
+        */
+       Editor.prototype.unRegisterPlugin = function(pluginName) {
+               delete this.plugins[pluginName].instance;
+               delete this.plugins[pluginName];
+       };
 
-               /**
-                * Update the edito toolbar
-                */
-               updateToolbar: function (noStatus) {
-                       this.toolbar.update(noStatus);
-               },
+       /**
+        * Update the editor toolbar
+        */
+       Editor.prototype.updateToolbar = function (noStatus) {
+               this.toolbar.update(noStatus);
+       };
 
-               /**
-                * Focus on the editor
-                */
-               focus: function () {
-                       switch (this.getMode()) {
-                               case 'wysiwyg':
-                                       this.iframe.focus();
-                                       break;
-                               case 'textmode':
-                                       this.textArea.focus();
-                                       break;
-                       }
-               },
+       /**
+        * Focus on the editor
+        */
+       Editor.prototype.focus = function () {
+               switch (this.getMode()) {
+                       case 'wysiwyg':
+                               this.iframe.focus();
+                               break;
+                       case 'textmode':
+                               this.textArea.focus();
+                               break;
+               }
+       };
 
-               /**
-                * Scroll the editor window to the current caret position
-                */
-               scrollToCaret: function () {
-                       if (!UserAgent.isIE) {
-                               var e = this.getSelection().getParentElement(),
-                                       w = this.iframe.getEl().dom.contentWindow ? this.iframe.getEl().dom.contentWindow : window,
-                                       h = w.innerHeight || w.height,
-                                       d = this.document,
-                                       t = d.documentElement.scrollTop || d.body.scrollTop;
-                               if (e.offsetTop > h+t || e.offsetTop < t) {
-                                       this.getSelection().getParentElement().scrollIntoView();
-                               }
+       /**
+        * Scroll the editor window to the current caret position
+        */
+       Editor.prototype.scrollToCaret = function () {
+               if (!UserAgent.isIE) {
+                       var e = this.getSelection().getParentElement(),
+                               w = this.iframe.getEl().dom.contentWindow ? this.iframe.getEl().dom.contentWindow : window,
+                               h = w.innerHeight || w.height,
+                               d = this.document,
+                               t = d.documentElement.scrollTop || d.body.scrollTop;
+                       if (e.offsetTop > h+t || e.offsetTop < t) {
+                               this.getSelection().getParentElement().scrollIntoView();
                        }
-               },
+               }
+       };
 
-               /**
-                * Add listeners
-                */
-               initEventsListening: function () {
-                       if (UserAgent.isOpera) {
-                               this.iframe.startListening();
-                       }
-                       // Add unload handler
-                       var iframe = this.iframe.getEl().dom;
-                       var self = this;
-                       Event.one(iframe.contentWindow ? iframe.contentWindow : iframe.contentDocument, 'unload', function (event) { return self.onUnload(event); });
-               },
+       /**
+        * Add listeners
+        */
+       Editor.prototype.initEventsListening = function () {
+               if (UserAgent.isOpera) {
+                       this.iframe.startListening();
+               }
+               // Add unload handler
+               var iframe = this.iframe.getEl().dom;
+               var self = this;
+               Event.one(iframe.contentWindow ? iframe.contentWindow : iframe.contentDocument, 'unload', function (event) { return self.onUnload(event); });
+       };
 
-               /**
-                * Make the editor framework visible
-                */
-               show: function () {
-                       document.getElementById('pleasewait' + this.editorId).style.display = 'none';
-                       document.getElementById('editorWrap' + this.editorId).style.visibility = 'visible';
-               },
+       /**
+        * Make the editor framework visible
+        */
+       Editor.prototype.show = function () {
+               document.getElementById('pleasewait' + this.editorId).style.display = 'none';
+               document.getElementById('editorWrap' + this.editorId).style.visibility = 'visible';
+       };
 
-               /**
-                * Append an entry at the end of the troubleshooting log
-                *
-                * @param       string          functionName: the name of the editor function writing to the log
-                * @param       string          text: the text of the message
-                * @param       string          type: the type of message
-                *
-                * @return      void
-                */
-               appendToLog: function (objectName, functionName, text, type) {
-                       HTMLArea.appendToLog(this.editorId, objectName, functionName, text, type);
-               },
+       /**
+        * Append an entry at the end of the troubleshooting log
+        *
+        * @param string functionName: the name of the editor function writing to the log
+        * @param string text: the text of the message
+        * @param string type: the type of message
+        * @return void
+        */
+       Editor.prototype.appendToLog = function (objectName, functionName, text, type) {
+               HTMLArea.appendToLog(this.editorId, objectName, functionName, text, type);
+       };
 
-               /**
-                * Iframe unload handler: Update the textarea for submission and cleanup
-                */
-               onUnload: function (event) {
-                       // Save the HTML content into the original textarea for submit, back/forward, etc.
-                       if (this.ready) {
-                               this.textArea.value = this.getHTML();
-                       }
-                       // Cleanup
-                       for (var pluginId in this.plugins) {
-                               this.unRegisterPlugin(pluginId);
-                       }
-                       Event.off(this.textarea);
-                       this.purgeListeners();
-                       RTEarea[this.editorId].editor = null;
-                       // ExtJS is not releasing any resources when the iframe is unloaded
-                       this.htmlArea.destroy();
-                       return true;
+       /**
+        * Iframe unload handler: Update the textarea for submission and cleanup
+        */
+       Editor.prototype.onUnload = function (event) {
+               // Save the HTML content into the original textarea for submit, back/forward, etc.
+               if (this.ready) {
+                       this.textArea.value = this.getHTML();
+               }
+               // Cleanup
+               for (var pluginId in this.plugins) {
+                       this.unRegisterPlugin(pluginId);
                }
-       });
+               Event.off(this.textarea);
+               RTEarea[this.editorId].editor = null;
+               // ExtJS is not releasing any resources when the iframe is unloaded
+               this.htmlArea.destroy();
+               return true;
+       };
 
        return Editor;
 
index f662643..f7a79d2 100644 (file)
@@ -80,8 +80,9 @@ define('TYPO3/CMS/Rtehtmlarea/Plugins/ContextMenu',
                        }, this.pageTSConfiguration));
                        // Monitor contextmenu clicks on the iframe
                        Event.on(this.editor.document.documentElement, 'contextmenu', function (event) { return self.show(event, event.target); });
-                       // Monitor editor being destroyed
-                       this.menu.mon(this.editor, 'beforedestroy', this.onBeforeDestroy, this, {single: true});
+                       // Monitor editor being unloaded
+                       var iframe = this.editor.iframe.getEl().dom;
+                       Event.one(iframe.contentWindow ? iframe.contentWindow : iframe.contentDocument, 'unload', function (event) { self.onBeforeDestroy(event); return  true; });
                },
                /**
                 * Create the menu items config
@@ -276,7 +277,7 @@ define('TYPO3/CMS/Rtehtmlarea/Plugins/ContextMenu',
                /**
                 * Handler invoked when the editor is about to be destroyed
                 */
-               onBeforeDestroy: function () {
+               onBeforeDestroy: function (event) {
                        this.menu.items.each(function (menuItem) {
                                Ext.QuickTips.unregister(menuItem);
                        });