[TASK] Migrate to ExtJS 4: Migrate RTE
authorStanislas Rolland <typo3@sjbr.ca>
Wed, 7 Dec 2011 00:43:45 +0000 (19:43 -0500)
committerSteffen Ritter <info@rs-websystems.de>
Fri, 16 Dec 2011 13:06:34 +0000 (14:06 +0100)
1. Migrate RTE.
2. Add soft hyphen insertion feature.

Change-Id: Ic81ecf9f682ead18680475534e27a267d6cc59e8
Resolves: #32200
Releases: 4.7
Reviewed-on: http://review.typo3.org/7106
Reviewed-by: Steffen Ritter
Tested-by: Steffen Ritter
Reviewed-by: Georg Ringer
42 files changed:
typo3/sysext/rtehtmlarea/class.tx_rtehtmlarea_base.php
typo3/sysext/rtehtmlarea/ext_localconf.php
typo3/sysext/rtehtmlarea/extensions/CharacterMap/class.tx_rtehtmlarea_charactermap.php
typo3/sysext/rtehtmlarea/extensions/CharacterMap/skin/htmlarea.css
typo3/sysext/rtehtmlarea/htmlarea/htmlarea.js
typo3/sysext/rtehtmlarea/htmlarea/plugins/AboutEditor/about-editor.js
typo3/sysext/rtehtmlarea/htmlarea/plugins/Acronym/acronym.js
typo3/sysext/rtehtmlarea/htmlarea/plugins/BlockElements/block-elements.js
typo3/sysext/rtehtmlarea/htmlarea/plugins/BlockStyle/block-style.js
typo3/sysext/rtehtmlarea/htmlarea/plugins/CharacterMap/character-map.js
typo3/sysext/rtehtmlarea/htmlarea/plugins/CharacterMap/locallang.xlf
typo3/sysext/rtehtmlarea/htmlarea/plugins/ContextMenu/context-menu.js
typo3/sysext/rtehtmlarea/htmlarea/plugins/CopyPaste/copy-paste.js
typo3/sysext/rtehtmlarea/htmlarea/plugins/DefaultClean/default-clean.js
typo3/sysext/rtehtmlarea/htmlarea/plugins/DefaultImage/default-image.js
typo3/sysext/rtehtmlarea/htmlarea/plugins/DefaultImage/locallang.xlf
typo3/sysext/rtehtmlarea/htmlarea/plugins/DefaultInline/default-inline.js
typo3/sysext/rtehtmlarea/htmlarea/plugins/DefaultLink/default-link.js
typo3/sysext/rtehtmlarea/htmlarea/plugins/DefinitionList/definition-list.js
typo3/sysext/rtehtmlarea/htmlarea/plugins/EditElement/edit-element.js
typo3/sysext/rtehtmlarea/htmlarea/plugins/EditorMode/editor-mode.js
typo3/sysext/rtehtmlarea/htmlarea/plugins/FindReplace/find-replace.js
typo3/sysext/rtehtmlarea/htmlarea/plugins/InlineElements/inline-elements.js
typo3/sysext/rtehtmlarea/htmlarea/plugins/InsertSmiley/insert-smiley.js
typo3/sysext/rtehtmlarea/htmlarea/plugins/Language/language.js
typo3/sysext/rtehtmlarea/htmlarea/plugins/PlainText/plain-text.js
typo3/sysext/rtehtmlarea/htmlarea/plugins/QuickTag/quick-tag.js
typo3/sysext/rtehtmlarea/htmlarea/plugins/RemoveFormat/remove-format.js
typo3/sysext/rtehtmlarea/htmlarea/plugins/SelectFont/select-font.js
typo3/sysext/rtehtmlarea/htmlarea/plugins/SpellChecker/spell-checker.js
typo3/sysext/rtehtmlarea/htmlarea/plugins/TYPO3Color/typo3color.js
typo3/sysext/rtehtmlarea/htmlarea/plugins/TYPO3HtmlParser/typo3html-parser.js
typo3/sysext/rtehtmlarea/htmlarea/plugins/TYPO3Image/typo3image.js
typo3/sysext/rtehtmlarea/htmlarea/plugins/TYPO3Link/typo3link.js
typo3/sysext/rtehtmlarea/htmlarea/plugins/TableOperations/table-operations.js
typo3/sysext/rtehtmlarea/htmlarea/plugins/TextIndicator/text-indicator.js
typo3/sysext/rtehtmlarea/htmlarea/plugins/TextStyle/text-style.js
typo3/sysext/rtehtmlarea/htmlarea/plugins/UndoRedo/undo-redo.js
typo3/sysext/rtehtmlarea/htmlarea/plugins/UserElements/user-elements.js
typo3/sysext/rtehtmlarea/htmlarea/skins/default/htmlarea.css
typo3/sysext/rtehtmlarea/pi2/class.tx_rtehtmlarea_pi2.php
typo3/sysext/t3skin/rtehtmlarea/htmlarea.css

index 5c8d4c5..664573f 100644 (file)
@@ -595,7 +595,7 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
                        bar, left, center, right, justifyfull,
                        bar, orderedlist, unorderedlist, definitionlist, definitionitem, outdent, indent,  bar, lefttoright, righttoleft, language, showlanguagemarks,
                        bar, textcolor, bgcolor, textindicator,
-                       bar, editelement, emoticon, insertcharacter, link, unlink, image, table,' . (($this->thisConfig['hideTableOperationsInToolbar'] && is_array($this->thisConfig['buttons.']) && is_array($this->thisConfig['buttons.']['toggleborders.']) && $this->thisConfig['buttons.']['toggleborders.']['keepInToolbar']) ? ' toggleborders,': '') . ' user, acronym, bar, findreplace, spellcheck,
+                       bar, editelement, emoticon, insertcharacter, insertsofthyphen, link, unlink, image, table,' . (($this->thisConfig['hideTableOperationsInToolbar'] && is_array($this->thisConfig['buttons.']) && is_array($this->thisConfig['buttons.']['toggleborders.']) && $this->thisConfig['buttons.']['toggleborders.']['keepInToolbar']) ? ' toggleborders,': '') . ' user, acronym, bar, findreplace, spellcheck,
                        bar, chMode, inserttag, removeformat, bar, copy, cut, paste, pastetoggle, pastebehaviour, bar, undo, redo, bar, showhelp, about, linebreak,
                        ' . ($this->thisConfig['hideTableOperationsInToolbar'] ? '': 'bar, toggleborders,') . ' bar, tableproperties, tablerestyle, bar, rowproperties, rowinsertabove, rowinsertunder, rowdelete, rowsplit, bar,
                        columnproperties, columninsertbefore, columninsertafter, columndelete, columnsplit, bar,
@@ -1543,4 +1543,4 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/class.tx_rtehtmlarea_base.php'])) {
        include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/class.tx_rtehtmlarea_base.php']);
 }
-?>
\ No newline at end of file
+?>
index 7b1e376..495c522 100644 (file)
@@ -126,7 +126,7 @@ $TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['BlockStyle'] = array();
 $TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['BlockStyle']['objectReference'] = 'EXT:'.$_EXTKEY.'/extensions/BlockStyle/class.tx_rtehtmlarea_blockstyle.php:&tx_rtehtmlarea_blockstyle';
 $TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['CharacterMap'] = array();
 $TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['CharacterMap']['objectReference'] = 'EXT:'.$_EXTKEY.'/extensions/CharacterMap/class.tx_rtehtmlarea_charactermap.php:&tx_rtehtmlarea_charactermap';
-$TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['CharacterMap']['addIconsToSkin'] = 0;
+$TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['CharacterMap']['addIconsToSkin'] = 1;
 $TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['Acronym'] = array();
 $TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['Acronym']['objectReference'] = 'EXT:'.$_EXTKEY.'/extensions/Acronym/class.tx_rtehtmlarea_acronym.php:&tx_rtehtmlarea_acronym';
 $TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['Acronym']['addIconsToSkin'] = 0;
index 6acfc75..8d9cf3b 100644 (file)
@@ -38,9 +38,10 @@ class tx_rtehtmlarea_charactermap extends tx_rtehtmlarea_api {
        protected $toolbar;                             // Reference to RTE toolbar array
        protected $LOCAL_LANG;                          // Frontend language array
 
-       protected $pluginButtons = 'insertcharacter';
+       protected $pluginButtons = 'insertcharacter,insertsofthyphen';
        protected $convertToolbarForHtmlAreaArray = array (
                'insertcharacter'       => 'InsertCharacter',
+               'insertsofthyphen'      => 'InsertSoftHyphen',
                );
 
        /**
index ab3f1aa..20cfd22 100644 (file)
@@ -3,3 +3,7 @@
        background-image: url('images/insertCharacter.gif') !important;
        background-position: 0 0 !important;
 }
+.htmlarea-action-soft-hyphen-insert {
+       background-image: url('images/insertSoftHyphen.gif') !important;
+       background-position: 0 0 !important;
+}
index dcd2351..9d3a7a6 100644 (file)
  */
        // Avoid re-initialization on AJax call when HTMLArea object was already initialized
 if (typeof(HTMLArea) == 'undefined') {
+/*
+ * MODIFIED Ext.EventManager
+ *
+ * HTMLArea will need to establish listeners on it's iframe's documentElement.
+ * This element does not belong to the document in which ExtJS is initialized.
+ * ExtJS's garbage collection will clean away this cached element and any listeners on it.
+ * Therefore, this sequence function will skipGarbageCollection on any element
+ * that does not belong to the document in which ExtJS is initialized.
+ */
+Ext.EventManager.getId = Ext.Function.createSequence(Ext.EventManager.getId, function (element) {
+       var id;
+
+        element = Ext.getDom(element);
+
+        if (element === document || element === window) {
+            id = element === document ? Ext.documentId : Ext.windowId;
+        }
+        else {
+            id = Ext.id(element);
+        }
+               // Skip garbage collection if the element does not belong to the document in which ExtJS is initialized
+       if (element && (element.ownerDocument !== document)) {
+               Ext.cache[id].skipGarbageCollection = true;
+       }
+       return id;
+});
        // Establish HTMLArea name space
-Ext.namespace('HTMLArea.CSS', 'HTMLArea.util.TYPO3', 'HTMLArea.util.Tips', 'HTMLArea.util.Color', 'Ext.ux.form', 'Ext.ux.menu', 'Ext.ux.Toolbar');
+Ext.namespace('HTMLArea.util.TYPO3', 'HTMLArea.util.Tips', 'HTMLArea.util.Color');
 Ext.apply(HTMLArea, {
        /***************************************************
         * COMPILED REGULAR EXPRESSIONS                    *
@@ -111,6 +137,16 @@ Ext.apply(HTMLArea, {
 /***************************************************
  *  EDITOR CONFIGURATION
  ***************************************************/
+Ext.define('HTMLArea.model.Default', {
+       extend: 'Ext.data.Model',
+       fields: [{
+                       name: 'text',
+                       type: 'string'
+               },{
+                       name: 'value',
+                       type: 'string'
+       }]
+});
 HTMLArea.Config = function (editorId) {
        this.editorId = editorId;
                // if the site is secure, create a secure iframe
@@ -153,7 +189,6 @@ HTMLArea.Config = function (editorId) {
        this.configDefaults = {
                all: {
                        xtype: 'htmlareabutton',
-                       disabledClass: 'buttonDisabled',
                        textMode: false,
                        selection: false,
                        dialog: false,
@@ -163,11 +198,12 @@ HTMLArea.Config = function (editorId) {
                htmlareabutton: {
                        cls: 'button',
                        overCls: 'buttonHover',
+                       scale: 'medium',
                                // Erratic behaviour of click event in WebKit and IE browsers
                        clickEvent: (Ext.isWebKit || Ext.isIE) ? 'mousedown' : 'click'
                },
                htmlareacombo: {
-                       cls: 'select',
+                       cls: 'htmlarea-combo',
                        typeAhead: true,
                        lastQuery: '',
                        triggerAction: 'all',
@@ -177,14 +213,14 @@ HTMLArea.Config = function (editorId) {
                        validateOnBlur: false,
                        submitValue: false,
                        forceSelection: true,
-                       mode: 'local',
+                       queryMode: 'local',
                        storeRoot: 'options',
-                       storeFields: [ { name: 'text'}, { name: 'value'}],
+                       model: 'HTMLArea.model.Default',
                        valueField: 'value',
                        displayField: 'text',
                        labelSeparator: '',
                        hideLabel: true,
-                       tpl: '<tpl for="."><div ext:qtip="{value}" style="text-align:left;font-size:11px;" class="x-combo-list-item">{text}</div></tpl>'
+                       template: '<div data-qtip="{value}" class="htmlarea-combo-list-item">{text}</div>'
                }
        };
 };
@@ -208,7 +244,7 @@ HTMLArea.Config = Ext.extend(HTMLArea.Config, {
         */
        registerButton: function (config) {
                config.itemId = config.id;
-               if (Ext.type(this.buttonsConfig[config.id])) {
+               if (this.buttonsConfig[config.id]) {
                        HTMLArea.appendToLog('', 'HTMLArea.Config', 'registerButton', 'A toolbar item with the same Id: ' + config.id + ' already exists and will be overidden.', 'warn');
                }
                        // Apply defaults
@@ -219,21 +255,32 @@ HTMLArea.Config = Ext.extend(HTMLArea.Config, {
                        case 'htmlareacombo':
                                if (config.options) {
                                                // Create combo array store
-                                       config.store = new Ext.data.ArrayStore({
-                                               autoDestroy:  true,
-                                               fields: config.storeFields,
-                                               data: config.options
+                                       config.store = Ext.create('Ext.data.ArrayStore', {
+                                               data: config.options,
+                                               model: config.model,
+                                               storeId: this.editorId + '-store-' + config.id
                                        });
                                } else if (config.storeUrl) {
                                                // Create combo json store
-                                       config.store = new Ext.data.JsonStore({
-                                               autoDestroy:  true,
+                                       config.store = Ext.create('Ext.data.Store', {
                                                autoLoad: true,
-                                               root: config.storeRoot,
-                                               fields: config.storeFields,
-                                               url: config.storeUrl
+                                               model: config.model,
+                                               proxy: {
+                                                       type: 'ajax',
+                                                       url: config.storeUrl,
+                                                       reader: {
+                                                               type: 'json',
+                                                               root: config.storeRoot
+                                                       }
+                                               },
+                                               storeId: this.editorId + '-store-' + config.id
                                        });
                                }
+                               if (!Ext.isObject(config.listConfig)) {
+                                       config.listConfig = {};
+                               }
+                               config.listConfig.getInnerTpl = function () { return config.template; };
+                               config.listConfig.cls = 'htmlarea-combo-list';
                                config.hideLabel = Ext.isEmpty(config.fieldLabel) || Ext.isIE6;
                                config.helpTitle = config.tooltip;
                                break;
@@ -244,7 +291,9 @@ HTMLArea.Config = Ext.extend(HTMLArea.Config, {
                                break;
                }
                config.cmd = config.id;
-               config.tooltip = { title: config.tooltip };
+               config.tooltip = {
+                       text: config.tooltip
+               };
                this.buttonsConfig[config.id] = config;
                return true;
        },
@@ -274,14 +323,16 @@ HTMLArea.Config = Ext.extend(HTMLArea.Config, {
  *  TOOLBAR COMPONENTS
  ***************************************************/
 /*
- * Ext.ux.HTMLAreaButton extends Ext.Button
+ * HTMLArea.toolbar.Button extends Ext.button.Button
  */
-Ext.ux.HTMLAreaButton = Ext.extend(Ext.Button, {
+Ext.define('HTMLArea.toolbar.Button', {
+       extend: 'Ext.button.Button',
+       alias: ['widget.htmlareabutton'],
        /*
         * Component initialization
         */
        initComponent: function () {
-               Ext.ux.HTMLAreaButton.superclass.initComponent.call(this);
+               this.callParent(arguments);
                this.addEvents(
                        /*
                         * @event HTMLAreaEventHotkey
@@ -330,13 +381,19 @@ Ext.ux.HTMLAreaButton = Ext.extend(Ext.Button, {
                return this.ownerCt;
        },
        /*
+        * Get the button itemId
+        */
+       getItemId: function() {
+               return this.itemId;
+       },
+       /*
         * Add properties and function to set button active or not depending on current selection
         */
        inactive: true,
        activeClass: 'buttonActive',
        setInactive: function (inactive) {
                this.inactive = inactive;
-               return inactive ? this.removeClass(this.activeClass) : this.addClass(this.activeClass);
+               return inactive ? this.removeCls(this.activeClass) : this.addCls(this.activeClass);
        },
        /*
         * Determine if the button should be enabled based on the current selection and context configuration property
@@ -372,9 +429,15 @@ Ext.ux.HTMLAreaButton = Ext.extend(Ext.Button, {
         * Handler invoked when the button is clicked
         */
        onButtonClick: function (button, event, key) {
+               var returnValue = true;
                if (!this.disabled) {
-                       if (!this.plugins[this.action](this.getEditor(), key || this.itemId) && event) {
+                       if (this.dialog && Ext.isObject(event)) {
+                               event.stopEvent();
+                               returnValue = false;
+                       }
+                       if (!this.plugins[0][this.action](this.getEditor(), key || this.getItemId()) && Ext.isObject(event)) {
                                event.stopEvent();
+                               returnValue = false;
                        }
                        if (Ext.isOpera) {
                                this.getEditor().focus();
@@ -385,7 +448,7 @@ Ext.ux.HTMLAreaButton = Ext.extend(Ext.Button, {
                                this.getToolbar().update();
                        }
                }
-               return false;
+               return returnValue;
        },
        /*
         * Handler invoked when the hotkey configured for this button is pressed
@@ -402,20 +465,22 @@ Ext.ux.HTMLAreaButton = Ext.extend(Ext.Button, {
                        if (!this.noAutoUpdate) {
                                this.setDisabled(!this.isInContext(mode, selectionEmpty, ancestors));
                        }
-                       this.plugins['onUpdateToolbar'](this, mode, selectionEmpty, ancestors, endPointsInSameBlock);
+                       this.plugins[0].onUpdateToolbar(this, mode, selectionEmpty, ancestors, endPointsInSameBlock);
                }
        }
 });
-Ext.reg('htmlareabutton', Ext.ux.HTMLAreaButton);
+
 /*
- * Ext.ux.Toolbar.HTMLAreaToolbarText extends Ext.Toolbar.TextItem
+ * HTMLArea.toolbar.TextItem extends Ext.Toolbar.TextItem
  */
-Ext.ux.Toolbar.HTMLAreaToolbarText = Ext.extend(Ext.Toolbar.TextItem, {
+Ext.define('HTMLArea.toolbar.TextItem', {
+       extend: 'Ext.toolbar.TextItem',
+       alias: ['widget.htmlareatoolbartext'],
        /*
-        * Constructor
+        * Initialize component
         */
        initComponent: function () {
-               Ext.ux.Toolbar.HTMLAreaToolbarText.superclass.initComponent.call(this);
+               this.callParent(arguments);
                this.addListener({
                        afterrender: {
                                fn: this.initEventListeners,
@@ -448,20 +513,22 @@ Ext.ux.Toolbar.HTMLAreaToolbarText = Ext.extend(Ext.Toolbar.TextItem, {
        onUpdateToolbar: function (mode, selectionEmpty, ancestors, endPointsInSameBlock) {
                this.setDisabled(mode === 'textmode' && !this.textMode);
                if (!this.disabled) {
-                       this.plugins['onUpdateToolbar'](this, mode, selectionEmpty, ancestors, endPointsInSameBlock);
+                       this.plugins[0].onUpdateToolbar(this, mode, selectionEmpty, ancestors, endPointsInSameBlock);
                }
        }
 });
-Ext.reg('htmlareatoolbartext', Ext.ux.Toolbar.HTMLAreaToolbarText);
+
 /*
- * Ext.ux.form.HTMLAreaCombo extends Ext.form.ComboBox
+ * HTMLArea.toolbar.ComboBox extends Ext.form.field.ComboBox
  */
-Ext.ux.form.HTMLAreaCombo = Ext.extend(Ext.form.ComboBox, {
+Ext.define('HTMLArea.toolbar.ComboBox', {
+       extend: 'Ext.form.field.ComboBox',
+       alias: ['widget.htmlareacombo'],
        /*
-        * Constructor
+        * Initialize component
         */
        initComponent: function () {
-               Ext.ux.form.HTMLAreaCombo.superclass.initComponent.call(this);
+               this.callParent(arguments);
                this.addEvents(
                        /*
                         * @event HTMLAreaEventHotkey
@@ -513,9 +580,21 @@ Ext.ux.form.HTMLAreaCombo = Ext.extend(Ext.form.ComboBox, {
                return this.ownerCt;
        },
        /*
+        * Get the combo itemId
+        */
+       getItemId: function() {
+               return this.itemId;
+       },
+       /*
+        * Get the combo store
+        */
+       getStore: function(){
+               return this.store;
+       },
+       /*
         * Handler invoked when an item is selected in the dropdown list
         */
-       onComboSelect: function (combo, record, index) {
+       onComboSelect: function (combo, records) {
                if (!combo.disabled) {
                        var editor = this.getEditor();
                                // In IE, reclaim lost focus on the editor iframe and restore the bookmarked selection
@@ -527,7 +606,7 @@ Ext.ux.form.HTMLAreaCombo = Ext.extend(Ext.form.ComboBox, {
                                }
                        }
                                // Invoke the plugin onChange handler
-                       this.plugins[this.action](editor, combo, record, index);
+                       this.plugins[0][this.action](editor, combo, records);
                                // In IE, bookmark the updated selection as the editor will be loosing focus
                        if (Ext.isIE) {
                                editor.focus();
@@ -546,7 +625,7 @@ Ext.ux.form.HTMLAreaCombo = Ext.extend(Ext.form.ComboBox, {
         * In IE, need to reclaim lost focus for the editor in order to restore the selection
         */
        onTriggerClick: function () {
-               Ext.ux.form.HTMLAreaCombo.superclass.onTriggerClick.call(this);
+               this.callParent(arguments);
                        // In IE, avoid focus being stolen and selection being lost
                if (Ext.isIE) {
                        this.triggered = true;
@@ -558,7 +637,7 @@ Ext.ux.form.HTMLAreaCombo = Ext.extend(Ext.form.ComboBox, {
         */
        onViewClick: function (doFocus) {
                        // Avoid stealing focus from the editor
-               Ext.ux.form.HTMLAreaCombo.superclass.onViewClick.call(this, false);
+               this.callParent([false]);
        },
        /*
         * Handler invoked in IE when the mouse moves out of the editor iframe
@@ -592,7 +671,7 @@ Ext.ux.form.HTMLAreaCombo = Ext.extend(Ext.form.ComboBox, {
         */
        onHotKey: function (key) {
                if (!this.disabled) {
-                       this.plugins.onHotKey(this.getEditor(), key);
+                       this.plugins[0].onHotKey(this.getEditor(), key);
                        if (Ext.isOpera) {
                                this.getEditor().focus();
                        }
@@ -606,7 +685,7 @@ Ext.ux.form.HTMLAreaCombo = Ext.extend(Ext.form.ComboBox, {
        onUpdateToolbar: function (mode, selectionEmpty, ancestors, endPointsInSameBlock) {
                this.setDisabled(mode === 'textmode' && !this.textMode);
                if (!this.disabled) {
-                       this.plugins['onUpdateToolbar'](this, mode, selectionEmpty, ancestors, endPointsInSameBlock);
+                       this.plugins[0].onUpdateToolbar(this, mode, selectionEmpty, ancestors, endPointsInSameBlock);
                }
        },
        /*
@@ -634,19 +713,21 @@ Ext.ux.form.HTMLAreaCombo = Ext.extend(Ext.form.ComboBox, {
                this.getStore().destroy();
        }
 });
-Ext.reg('htmlareacombo', Ext.ux.form.HTMLAreaCombo);
+
 /***************************************************
  *  EDITOR FRAMEWORK
  ***************************************************/
 /*
- * HTMLArea.Toolbar extends Ext.Container
+ * HTMLArea.toolbar.Toolbar extends Ext.container.Container
  */
-HTMLArea.Toolbar = Ext.extend(Ext.Container, {
+Ext.define('HTMLArea.toolbar.Toolbar', {
+       extend: 'Ext.container.Container',
+       alias: ['widget.htmlareatoolbar'],
        /*
-        * Constructor
+        * Initialize component
         */
        initComponent: function () {
-               HTMLArea.Toolbar.superclass.initComponent.call(this);
+               this.callParent(arguments);
                this.addEvents(
                        /*
                         * @event HTMLAreaEventToolbarUpdate
@@ -655,7 +736,7 @@ HTMLArea.Toolbar = Ext.extend(Ext.Container, {
                        'HTMLAreaEventToolbarUpdate'
                );
                        // Build the deferred toolbar update task
-               this.updateLater = new Ext.util.DelayedTask(this.update, this);
+               this.updateLater = Ext.create('Ext.util.DelayedTask', this.update, this);
                        // Add the toolbar items
                this.addItems();
                this.addListener({
@@ -696,12 +777,13 @@ HTMLArea.Toolbar = Ext.extend(Ext.Container, {
                        // Walk through the editor toolbar configuration nested arrays: [ toolbar [ row [ group ] ] ]
                var firstOnRow = true;
                var firstInGroup = true;
+               var itemsConfig = [];
                Ext.each(editor.config.toolbar, function (row) {
                        if (!firstOnRow) {
                                        // If a visible item was added to the previous line
-                               this.add({
+                               itemsConfig.push({
                                        xtype: 'tbspacer',
-                                       cls: 'x-form-clear-left'
+                                       cls: 'htmlarea-clear-left'
                                });
                        }
                        firstOnRow = true;
@@ -710,25 +792,25 @@ HTMLArea.Toolbar = Ext.extend(Ext.Container, {
                                        // To do: this.config.keepButtonGroupTogether ...
                                if (!firstOnRow && !firstInGroup) {
                                                // If a visible item was added to the line
-                                       this.add({
+                                       itemsConfig.push({
                                                xtype: 'tbseparator',
-                                               cls: 'separator'
+                                               cls: 'htmlarea-toolbar-separator'
                                        });
                                }
                                firstInGroup = true;
                                        // Add each item
                                Ext.each(group, function (item) {
                                        if (item == 'space') {
-                                               this.add({
+                                               itemsConfig.push({
                                                        xtype: 'tbspacer',
-                                                       cls: 'space'
+                                                       cls: 'htmlarea-toolbar-spacer'
                                                });
                                        } else {
                                                        // Get the item's config as registered by some plugin
                                                var itemConfig = editor.config.buttonsConfig[item];
                                                if (!Ext.isEmpty(itemConfig)) {
                                                        itemConfig.id = this.editorId + '-' + itemConfig.id;
-                                                       this.add(itemConfig);
+                                                       itemsConfig.push(itemConfig);
                                                        firstInGroup = firstInGroup && itemConfig.hidden;
                                                        firstOnRow = firstOnRow && firstInGroup;
                                                }
@@ -739,16 +821,17 @@ HTMLArea.Toolbar = Ext.extend(Ext.Container, {
                        }, this);
                        return true;
                }, this);
-               this.add({
+               itemsConfig.push({
                        xtype: 'tbspacer',
-                       cls: 'x-form-clear-left'
+                       cls: 'htmlarea-clear-left'
                });
+               this.add(itemsConfig);
        },
        /*
         * Retrieve a toolbar item by itemId
         */
        getButton: function (buttonId) {
-               return this.find('itemId', buttonId)[0];
+               return this.getComponent(buttonId);
        },
        /*
         * Update the state of the toolbar
@@ -771,19 +854,20 @@ HTMLArea.Toolbar = Ext.extend(Ext.Container, {
         */
        onBeforeDestroy: function () {
                this.removeAll(true);
-               return true;
        }
 });
-Ext.reg('htmlareatoolbar', HTMLArea.Toolbar);
+
 /*
- * HTMLArea.Iframe extends Ext.BoxComponent
+ * HTMLArea.Iframe extends Ext.Component
  */
-HTMLArea.Iframe = Ext.extend(Ext.BoxComponent, {
+Ext.define('HTMLArea.Iframe', {
+       extend: 'Ext.Component',
+       alias: ['widget.htmlareaiframe'],
        /*
-        * Constructor
+        * Initialize component
         */
        initComponent: function () {
-               HTMLArea.Iframe.superclass.initComponent.call(this);
+               this.callParent(arguments);
                this.addEvents(
                        /*
                         * @event HTMLAreaEventIframeReady
@@ -807,14 +891,14 @@ HTMLArea.Iframe = Ext.extend(Ext.BoxComponent, {
                        }
                });
                this.config = this.getEditor().config;
-               this.htmlRenderer = new HTMLArea.DOM.Walker({
+               this.htmlRenderer = Ext.create('HTMLArea.DOM.Walker', {
                        keepComments: !this.config.htmlRemoveComments,
                        removeTags: this.config.htmlRemoveTags,
                        removeTagsAndContents: this.config.htmlRemoveTagsAndContents,
                        baseUrl: this.config.baseURL
                });
                if (!this.config.showStatusBar) {
-                       this.addClass('noStatusBar');
+                       this.addCls('noStatusBar');
                }
        },
        /*
@@ -864,13 +948,13 @@ HTMLArea.Iframe = Ext.extend(Ext.BoxComponent, {
         * Get a reference to the toolbar
         */
        getToolbar: function () {
-               return this.ownerCt.getTopToolbar();
+               return this.ownerCt.toolbar;
        },
        /*
         * Get a reference to the statusBar
         */
        getStatusBar: function () {
-               return this.ownerCt.getBottomToolbar();
+               return this.ownerCt.statusBar;
        },
        /*
         * Get a reference to a button
@@ -883,43 +967,19 @@ HTMLArea.Iframe = Ext.extend(Ext.BoxComponent, {
         */
        ready: false,
        /*
-        * Create the iframe element at rendering time
-        */
-       onRender: function (ct, position){
-                       // from Ext.Component
-               if (!this.el && this.autoEl) {
-                       if (Ext.isString(this.autoEl)) {
-                               this.el = document.createElement(this.autoEl);
-                       } else {
-                                       // ExtJS Default method will not work with iframe element
-                               this.el = Ext.DomHelper.append(ct, this.autoEl, true);
-                       }
-                       if (!this.el.id) {
-                               this.el.id = this.getId();
-                       }
-               }
-                       // from Ext.BoxComponent
-               if (this.resizeEl){
-                       this.resizeEl = Ext.get(this.resizeEl);
-               }
-               if (this.positionEl){
-                       this.positionEl = Ext.get(this.positionEl);
-               }
-       },
-       /*
         * Proceed to build the iframe document head and ensure style sheets are available after the iframe document becomes available
         */
        initializeIframe: function () {
                var iframe = this.getEl().dom;
                        // All browsers
                if (!iframe || (!iframe.contentWindow && !iframe.contentDocument)) {
-                       this.initializeIframe.defer(50, this);
+                       Ext.Function.defer(this.initializeIframe, 50, this);
                        // All except WebKit
                } else if (iframe.contentWindow && !Ext.isWebKit && (!iframe.contentWindow.document || !iframe.contentWindow.document.documentElement)) {
-                       this.initializeIframe.defer(50, this);
+                       Ext.Function.defer(this.initializeIframe, 50, this);
                        // WebKit
                } else if (Ext.isWebKit && (!iframe.contentDocument.documentElement || !iframe.contentDocument.body)) {
-                       this.initializeIframe.defer(50, this);
+                       Ext.Function.defer(this.initializeIframe, 50, this);
                } else {
                        this.document = iframe.contentWindow ? iframe.contentWindow.document : iframe.contentDocument;
                        this.getEditor().document = this.document;
@@ -927,12 +987,9 @@ HTMLArea.Iframe = Ext.extend(Ext.BoxComponent, {
                        this.getEditor()._iframe = iframe;
                        this.createHead();
                                // Style the document body
-                       Ext.get(this.document.body).addClass('htmlarea-content-body');
+                       Ext.fly(this.document.body).addCls('htmlarea-content-body');
                                // Start listening to things happening in the iframe
-                               // For some unknown reason, this is too early for Opera
-                       if (!Ext.isOpera) {
-                               this.startListening();
-                       }
+                       this.startListening();
                                // Hide the iframe
                        this.hide();
                                // Set iframe ready
@@ -996,13 +1053,11 @@ HTMLArea.Iframe = Ext.extend(Ext.BoxComponent, {
         * Focus on the iframe
         */
        focus: function () {
-               try {
-                       if (Ext.isWebKit) {
-                               this.getEl().dom.focus();
-                       } else {
-                               this.getEl().dom.contentWindow.focus();
-                       }
-               } catch(e) { }
+               if (Ext.isWebKit) {
+                       this.getEl().dom.focus();
+               } else {
+                       this.getEl().dom.contentWindow.focus();
+               }
        },
        /*
         * Flag indicating whether the framework is inside a tab or inline element that may be hidden
@@ -1116,7 +1171,7 @@ HTMLArea.Iframe = Ext.extend(Ext.BoxComponent, {
         */
        startListening: function () {
                        // Create keyMap so that plugins may bind key handlers
-               this.keyMap = new Ext.KeyMap(Ext.get(this.document.documentElement), [], (Ext.isIE || Ext.isWebKit) ? 'keydown' : 'keypress');
+               this.keyMap = Ext.create('Ext.util.KeyMap', Ext.get(this.document.documentElement), [], (Ext.isIE || Ext.isWebKit) ? 'keydown' : 'keypress');
                        // Special keys map
                this.keyMap.addBinding([
                        {
@@ -1176,7 +1231,7 @@ HTMLArea.Iframe = Ext.extend(Ext.BoxComponent, {
                        }
                });
                        // Make hot key map available, even if empty, so that plugins may add bindings
-               this.hotKeyMap = new Ext.KeyMap(Ext.get(this.document.documentElement));
+               this.hotKeyMap = Ext.create('Ext.util.KeyMap', Ext.get(this.document.documentElement));
                if (!Ext.isEmpty(hotKeys)) {
                        this.hotKeyMap.addBinding({
                                key: hotKeys,
@@ -1184,7 +1239,8 @@ HTMLArea.Iframe = Ext.extend(Ext.BoxComponent, {
                                shift: false,
                                alt: false,
                                handler: this.onHotKey,
-                               scope: this
+                               scope: this,
+                               defaultEventAction: 'stopEvent'
                        });
                }
                this.mon(Ext.get(this.document.documentElement), (Ext.isIE || Ext.isWebKit) ? 'keydown' : 'keypress', this.onAnyKey, this);
@@ -1247,7 +1303,7 @@ HTMLArea.Iframe = Ext.extend(Ext.BoxComponent, {
        onPaste: function (event) {
                        // Make src and href urls absolute
                if (Ext.isGecko) {
-                       HTMLArea.DOM.makeUrlsAbsolute.defer(50, this, [this.getEditor().document.body, this.config.baseURL, this.htmlRenderer]);
+                       Ext.Function.defer(HTMLArea.DOM.makeUrlsAbsolute, 50, this, [this.getEditor().document.body, this.config.baseURL, this.htmlRenderer]);
                }
        },
        /*
@@ -1256,11 +1312,11 @@ HTMLArea.Iframe = Ext.extend(Ext.BoxComponent, {
        onDrop: function (event, target) {
                        // Clean up span elements added by WebKit
                if (Ext.isWebKit) {
-                       this.getEditor().cleanAppleStyleSpans.defer(50, this.getEditor(), [this.getEditor().document.body]);
+                       Ext.Function.defer(this.getEditor().cleanAppleStyleSpans, 50, this.getEditor(), [this.getEditor().document.body]);
                }
                        // Make src url absolute in Firefox
                if (Ext.isGecko) {
-                       HTMLArea.DOM.makeUrlsAbsolute.defer(50, this, [target, this.config.baseURL, this.htmlRenderer]);
+                       Ext.Function.defer(HTMLArea.DOM.makeUrlsAbsolute, 50, this, [target, this.config.baseURL, this.htmlRenderer]);
                }
                this.getToolbar().updateLater.delay(100);
        },
@@ -1382,8 +1438,7 @@ HTMLArea.Iframe = Ext.extend(Ext.BoxComponent, {
                        return false;
                }
                var hotKey = String.fromCharCode(key).toLowerCase();
-               this.getButton(this.config.hotKeyList[hotKey].cmd).fireEvent('HTMLAreaEventHotkey', hotKey, event);
-               return false;
+               return this.getButton(this.config.hotKeyList[hotKey].cmd).fireEvent('HTMLAreaEventHotkey', hotKey, event);
        },
        /*
         * Cleanup
@@ -1418,18 +1473,20 @@ HTMLArea.Iframe = Ext.extend(Ext.BoxComponent, {
                return true;
        }
 });
-Ext.reg('htmlareaiframe', HTMLArea.Iframe);
+
 /*
- * HTMLArea.StatusBar extends Ext.Container
+ * HTMLArea.StatusBar extends Ext.container.Container
  */
-HTMLArea.StatusBar = Ext.extend(Ext.Container, {
+Ext.define('HTMLArea.StatusBar', {
+       extend: 'Ext.container.Container',
+       alias: ['widget.htmlareastatusbar'],
        /*
-        * Constructor
+        * Initialize component
         */
        initComponent: function () {
-               HTMLArea.StatusBar.superclass.initComponent.call(this);
+               this.callParent(arguments);
                        // Build the deferred word count update task
-               this.updateWordCountLater = new Ext.util.DelayedTask(this.updateWordCount, this);
+               this.updateWordCountLater = Ext.create('Ext.util.DelayedTask', this.updateWordCount, this);
                this.addListener({
                        render: {
                                fn: this.addComponents,
@@ -1453,11 +1510,11 @@ HTMLArea.StatusBar = Ext.extend(Ext.Container, {
                });
                        // Monitor toolbar updates in order to refresh the contents of the statusbar
                        // The toolbar must have been rendered
-               this.mon(this.ownerCt.toolbar, 'HTMLAreaEventToolbarUpdate', this.onUpdateToolbar, this);
+               this.mon(this.getToolbar(), 'HTMLAreaEventToolbarUpdate', this.onUpdateToolbar, this);
                        // Monitor editor changing mode
                this.mon(this.getEditor(), 'HTMLAreaEventModeChange', this.onModeChange, this);
                        // Monitor word count change
-               this.mon(this.ownerCt.iframe, 'HTMLAreaEventWordCountChange', this.onWordCountChange, this);
+               this.mon(this.getIframe(), 'HTMLAreaEventWordCountChange', this.onWordCountChange, this);
        },
        /*
         * editorId should be set in config
@@ -1470,22 +1527,34 @@ HTMLArea.StatusBar = Ext.extend(Ext.Container, {
                return RTEarea[this.editorId].editor;
        },
        /*
+        * Get a reference to the toolbar
+        */
+       getToolbar: function() {
+               return this.ownerCt.toolbar;
+       },
+       /*
+        * Get a reference to the editor iframe
+        */
+       getIframe: function() {
+               return this.ownerCt.iframe;
+       },
+       /*
         * Create span elements to display when the status bar tree or a message when the editor is in text mode
         */
        addComponents: function () {
-               this.statusBarWordCount = Ext.DomHelper.append(this.getEl(), {
+               this.statusBarWordCount = Ext.core.DomHelper.append(this.getEl(), {
                        id: this.editorId + '-statusBarWordCount',
                        tag: 'span',
                        cls: 'statusBarWordCount',
                        html: '&nbsp;'
                }, true);
-               this.statusBarTree = Ext.DomHelper.append(this.getEl(), {
+               this.statusBarTree = Ext.core.DomHelper.append(this.getEl(), {
                        id: this.editorId + '-statusBarTree',
                        tag: 'span',
                        cls: 'statusBarTree',
                        html: HTMLArea.localize('Path') + ': '
                }, true).setVisibilityMode(Ext.Element.DISPLAY).setVisible(true);
-               this.statusBarTextMode = Ext.DomHelper.append(this.getEl(), {
+               this.statusBarTextMode = Ext.core.DomHelper.append(this.getEl(), {
                        id: this.editorId + '-statusBarTextMode',
                        tag: 'span',
                        cls: 'statusBarTextMode',
@@ -1498,7 +1567,7 @@ HTMLArea.StatusBar = Ext.extend(Ext.Container, {
        clear: function () {
                this.statusBarTree.removeAllListeners();
                Ext.each(this.statusBarTree.query('a'), function (node) {
-                       Ext.QuickTips.unregister(node);
+                       Ext.tip.QuickTipManager.unregister(node);
                        Ext.get(node).dom.ancestor = null;
                        Ext.destroy(node);
                });
@@ -1520,7 +1589,7 @@ HTMLArea.StatusBar = Ext.extend(Ext.Container, {
                                classes = new Array(),
                                classText;
                        this.clear();
-                       var path = Ext.DomHelper.append(this.statusBarTree, {
+                       var path = Ext.core.DomHelper.append(this.statusBarTree, {
                                tag: 'span',
                                html: HTMLArea.localize('Path') + ': '
                        },true);
@@ -1549,22 +1618,22 @@ HTMLArea.StatusBar = Ext.extend(Ext.Container, {
                                        }
                                        text += classText;
                                }
-                               var element = Ext.DomHelper.insertAfter(path, {
+                               var element = Ext.core.DomHelper.insertAfter(path, {
                                        tag: 'a',
                                        href: '#',
-                                       'ext:qtitle': HTMLArea.localize('statusBarStyle'),
-                                       'ext:qtip': ancestor.style.cssText.split(';').join('<br />'),
+                                       'data-qtitle': HTMLArea.localize('statusBarStyle'),
+                                       'data-qtip': ancestor.style.cssText.split(';').join('<br />'),
                                        html: text
                                }, true);
-                                       // Ext.DomHelper does not honour the custom attribute
+                                       // Ext.core.DomHelper does not honour the custom attribute
                                element.dom.ancestor = ancestor;
                                element.on('click', this.onClick, this);
                                element.on('mousedown', this.onClick, this);
                                if (!Ext.isOpera) {
-                                       element.on('contextmenu', this.onContextMenu, this);
+                                       element.on('contextmenu', this.onContextMenu, this, {stopEvent: true});
                                }
                                if (index) {
-                                       Ext.DomHelper.insertAfter(element, {
+                                       Ext.core.DomHelper.insertAfter(element, {
                                                tag: 'span',
                                                html: String.fromCharCode(0xbb)
                                        });
@@ -1688,19 +1757,20 @@ HTMLArea.StatusBar = Ext.extend(Ext.Container, {
                return true;
        }
 });
-Ext.reg('htmlareastatusbar', HTMLArea.StatusBar);
+
 /*
- * HTMLArea.Framework extends Ext.Panel
+ * HTMLArea.Framework extends Ext.panel.Panel
  */
-HTMLArea.Framework = Ext.extend(Ext.Panel, {
+Ext.define('HTMLArea.Framework', {
+       extend: 'Ext.panel.Panel',
        /*
-        * Constructor
+        * Initialize component
         */
        initComponent: function () {
-               HTMLArea.Framework.superclass.initComponent.call(this);
+               this.callParent(arguments);
                        // Set some references
-               this.toolbar = this.getTopToolbar();
-               this.statusBar = this.getBottomToolbar();
+               this.toolbar = this.getDockedComponent('toolbar');
+               this.statusBar = this.getDockedComponent('statusbar');
                this.iframe = this.getComponent('iframe');
                this.textAreaContainer = this.getComponent('textAreaContainer');
                this.addEvents(
@@ -1732,12 +1802,10 @@ HTMLArea.Framework = Ext.extend(Ext.Panel, {
         * Initiate events monitoring
         */
        initEventListeners: function () {
-                       // Make the framework resizable, if configured by the user
-               this.makeResizable();
                        // Monitor textArea container becoming shown or hidden as it may change the height of the status bar
-               this.mon(this.textAreaContainer, 'show', this.resizable ? this.onTextAreaShow : this.onWindowResize, this);
+               this.mon(this.textAreaContainer, 'show', this.resizable ? this.onResize : this.onWindowResize, this);
                        // Monitor iframe becoming shown or hidden as it may change the height of the status bar
-               this.mon(this.iframe, 'show', this.resizable ? this.onIframeShow : this.onWindowResize, this);
+               this.mon(this.iframe, 'show', this.resizable ? this.onResize : this.onWindowResize, this);
                        // Monitor window resizing
                Ext.EventManager.onWindowResize(this.onWindowResize, this);
                        // If the textarea is inside a form, on reset, re-initialize the HTMLArea content and update the toolbar
@@ -1753,7 +1821,7 @@ HTMLArea.Framework = Ext.extend(Ext.Panel, {
                }
                this.addListener({
                        resize: {
-                               fn: this.onFrameworkResize
+                               fn: this.onResize
                        }
                });
        },
@@ -1787,11 +1855,6 @@ HTMLArea.Framework = Ext.extend(Ext.Panel, {
         */
        nestedParentElements: {},
        /*
-        * Whether the framework should be made resizable
-        * May be set in config
-        */
-       resizable: false,
-       /*
         * Maximum height to which the framework may resized (in pixels)
         * May be set in config
         */
@@ -1810,7 +1873,7 @@ HTMLArea.Framework = Ext.extend(Ext.Panel, {
         */
        doLayout: function () {
                if (!this.isNested || HTMLArea.util.TYPO3.allElementsAreDisplayed(this.nestedParentElements.sorted)) {
-                       HTMLArea.Framework.superclass.doLayout.call(this);
+                       this.callParent(arguments);
                } 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);
@@ -1823,39 +1886,15 @@ HTMLArea.Framework = Ext.extend(Ext.Panel, {
         */
        onLayout: function () {
                if (!this.isNested || HTMLArea.util.TYPO3.allElementsAreDisplayed(this.nestedParentElements.sorted)) {
-                       HTMLArea.Framework.superclass.onLayout.call(this);
+                       this.callParent(arguments);
                } 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 sizes
-                               HTMLArea.util.TYPO3.accessParentElements(parentElements, 'HTMLArea.Framework.superclass.onLayout.call(args[0])', [this]);
+                       HTMLArea.util.TYPO3.accessParentElements(parentElements, 'HTMLArea.Framework.superclass.onLayout.call(args[0])', [this]);
                }
        },
        /*
-        * Make the framework resizable, if configured
-        */
-       makeResizable: function () {
-               if (this.resizable) {
-                       this.addClass('resizable');
-                       this.resizer = new Ext.Resizable(this.getEl(), {
-                               minWidth: 300,
-                               maxHeight: this.maxHeight,
-                               dynamic: false
-                       });
-                       this.resizer.on('resize', this.onHtmlAreaResize, this);
-               }
-       },
-       /*
-        * Resize the framework when the resizer handles are used
-        */
-       onHtmlAreaResize: function (resizer, width, height, event) {
-                       // Set width first as it may change the height of the toolbar and of the statusBar
-               this.setWidth(width);
-                       // Set height of iframe and textarea
-               this.iframe.setHeight(this.getInnerHeight());
-               this.textArea.setSize(this.getInnerWidth(), this.getInnerHeight());
-       },
-       /*
         * Size the iframe according to initial textarea size as set by Page and User TSConfig
         */
        onWindowResize: function (width, height) {
@@ -1875,15 +1914,15 @@ HTMLArea.Framework = Ext.extend(Ext.Panel, {
                var frameworkHeight = parseInt(this.textAreaInitialSize.height);
                if (this.textAreaInitialSize.width.indexOf('%') === -1) {
                                // Width is specified in pixels
-                       var frameworkWidth = parseInt(this.textAreaInitialSize.width) - this.getFrameWidth();
+                       var frameworkWidth = parseInt(this.textAreaInitialSize.width);
                } else {
                                // Width is specified in %
                        if (Ext.isNumber(width)) {
                                        // Framework sizing on actual window resize
-                               var frameworkWidth = parseInt(((width - this.textAreaInitialSize.wizardsWidth - (this.fullScreen ? 10 : Ext.getScrollBarWidth()) - this.getBox().x - 15) * parseInt(this.textAreaInitialSize.width))/100);
+                               var frameworkWidth = parseInt(((width - this.textAreaInitialSize.wizardsWidth - (this.fullScreen ? 10 : Ext.getScrollbarSize().width) - this.getBox().x - 15) * parseInt(this.textAreaInitialSize.width))/100);
                        } else {
                                        // Initial framework sizing
-                               var frameworkWidth = parseInt(((HTMLArea.util.TYPO3.getWindowSize().width - this.textAreaInitialSize.wizardsWidth - (this.fullScreen ? 10 : Ext.getScrollBarWidth()) - this.getBox().x - 15) * parseInt(this.textAreaInitialSize.width))/100);
+                               var frameworkWidth = parseInt(((HTMLArea.util.TYPO3.getWindowSize().width - this.textAreaInitialSize.wizardsWidth - (this.fullScreen ? 10 : Ext.getScrollbarSize().width) - this.getBox().x - 15) * parseInt(this.textAreaInitialSize.width))/100);
                        }
                }
                if (this.resizable) {
@@ -1896,33 +1935,25 @@ HTMLArea.Framework = Ext.extend(Ext.Panel, {
        /*
         * Resize the framework components
         */
-       onFrameworkResize: function () {
-               this.iframe.setSize(this.getInnerWidth(), this.getInnerHeight());
-               this.textArea.setSize(this.getInnerWidth(), this.getInnerHeight());
-       },
-       /*
-        * Adjust the height to the changing size of the statusbar when the textarea is shown
-        */
-       onTextAreaShow: function () {
-               this.iframe.setHeight(this.getInnerHeight());
-               this.textArea.setHeight(this.getInnerHeight());
-       },
-       /*
-        * Adjust the height to the changing size of the statusbar when the iframe is shown
-        */
-       onIframeShow: function () {
+       onResize: function () {
                if (this.getInnerHeight() <= 0) {
                        this.onWindowResize();
                } else {
-                       this.iframe.setHeight(this.getInnerHeight());
-                       this.textArea.setHeight(this.getInnerHeight());
+                       this.iframe.setSize(this.getInnerWidth() - 3, this.getInnerHeight() - 3);
+                       this.textArea.setSize(this.getInnerWidth(), this.getInnerHeight());
                }
        },
        /*
         * Calculate the height available for the editing iframe
         */
        getInnerHeight: function () {
-               return this.getSize().height - this.toolbar.getHeight() - this.statusBar.getHeight() -  5;
+               return this.getSize().height - this.toolbar.getHeight() - this.statusBar.getHeight();
+       },
+       /*
+        * Calculate the width available for the editing iframe
+        */
+       getInnerWidth: function () {
+               return this.getSize().width - this.frameSize.right - this.frameSize.left;
        },
        /*
         * Fire the editor when all components of the framework are rendered and ready
@@ -1939,7 +1970,7 @@ HTMLArea.Framework = Ext.extend(Ext.Panel, {
                        this.onWindowResize();
                        this.fireEvent('HTMLAreaEventFrameworkReady');
                } else {
-                       this.onIframeReady.defer(50, this);
+                       Ext.Function.defer(this.onIframeReady, 50, this);
                }
        },
        /*
@@ -1980,16 +2011,17 @@ HTMLArea.Framework = Ext.extend(Ext.Panel, {
                return true;
        }
 });
-Ext.reg('htmlareaframework', HTMLArea.Framework);
+
 /***************************************************
  *  HTMLArea.Editor extends Ext.util.Observable
  ***************************************************/
-HTMLArea.Editor = Ext.extend(Ext.util.Observable, {
+Ext.define('HTMLArea.Editor', {
+       extend: 'Ext.util.Observable',
        /*
         * HTMLArea.Editor constructor
         */
        constructor: function (config) {
-               HTMLArea.Editor.superclass.constructor.call(this, {});
+               this.callParent([{}]);
                        // Save the config
                this.config = config;
                        // Establish references to this editor
@@ -2033,7 +2065,7 @@ HTMLArea.Editor = Ext.extend(Ext.util.Observable, {
                        }
                }, this);
                        // Create Ajax object
-               this.ajax = new HTMLArea.Ajax({
+               this.ajax = Ext.create('HTMLArea.Ajax', {
                        editor: this
                });
                        // Initialize keyboard input inhibit flag
@@ -2050,6 +2082,7 @@ HTMLArea.Editor = Ext.extend(Ext.util.Observable, {
                         */
                        'HTMLAreaEventModeChange'
                );
+               return this;
        },
        /*
         * Flag set to true when the editor initialization has completed
@@ -2064,27 +2097,42 @@ HTMLArea.Editor = Ext.extend(Ext.util.Observable, {
         */
        generate: function () {
                        // Create the editor framework
-               this.htmlArea = new HTMLArea.Framework({
+               this.htmlArea = Ext.create('HTMLArea.Framework', {
                        id: this.editorId + '-htmlArea',
-                       layout: 'anchor',
-                       baseCls: 'htmlarea',
+                       layout: 'auto',
+                       renderTo: this.textArea.parent(),
+                       cls: 'htmlarea',
+                       frame: true,
                        editorId: this.editorId,
                        textArea: this.textArea,
                        textAreaInitialSize: this.textAreaInitialSize,
                        fullScreen: this.config.fullScreen,
                        resizable: this.config.resizable,
+                       minWidth: 300,
                        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
-                       },
+                       dockedItems: [{
+                                               // The toolbar
+                                       xtype: 'htmlareatoolbar',
+                                       dock: 'top',
+                                       itemId: 'toolbar',
+                                       id: this.editorId + '-toolbar',
+                                       anchor: '100%',
+                                       layout: 'anchor',
+                                       cls: 'toolbar',
+                                       editorId: this.editorId
+                               },{
+                                                       // The status bar
+                                       xtype: 'htmlareastatusbar',
+                                       dock: 'bottom',
+                                       itemId: 'statusbar',
+                                       id: this.editorId + '-statusbar',
+                                       anchor: '100%',
+                                       cls: 'statusBar',
+                                       editorId: this.editorId
+                               }
+                       ],
                        items: [{
                                                // The iframe
                                        xtype: 'htmlareaiframe',
@@ -2102,8 +2150,8 @@ HTMLArea.Editor = Ext.extend(Ext.util.Observable, {
                                        nestedParentElements: this.nestedParentElements,
                                        editorId: this.editorId
                                },{
-                                               // Box container for the textarea
-                                       xtype: 'box',
+                                               // Container for the textarea
+                                       xtype: 'component',
                                        itemId: 'textAreaContainer',
                                        anchor: '100%',
                                        width: (this.textAreaInitialSize.width.indexOf('%') === -1) ? parseInt(this.textAreaInitialSize.width) : 300,
@@ -2127,18 +2175,11 @@ HTMLArea.Editor = Ext.extend(Ext.util.Observable, {
                                                }
                                        }
                                }
-                       ],
-                               // 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.toolbar = this.htmlArea.getDockedComponent('toolbar');
+               this.statusBar = this.htmlArea.getDockedComponent('statusbar');
                this.iframe = this.htmlArea.getComponent('iframe');
                this.textAreaContainer = this.htmlArea.getComponent('textAreaContainer');
                        // Get triggered when the framework becomes ready
@@ -2285,7 +2326,7 @@ HTMLArea.Editor = Ext.extend(Ext.util.Observable, {
                var plugin = HTMLArea[pluginName],
                        isRegistered = false;
                if (typeof(plugin) !== 'undefined' && Ext.isFunction(plugin)) {
-                       var pluginInstance = new plugin(this, pluginName);
+                       var pluginInstance = Ext.create(plugin, this, pluginName);
                        if (pluginInstance) {
                                var pluginInformation = pluginInstance.getPluginInformation();
                                pluginInformation.instance = pluginInstance;
@@ -2343,9 +2384,6 @@ HTMLArea.Editor = Ext.extend(Ext.util.Observable, {
         * Add listeners
         */
        initEventsListening: function () {
-               if (Ext.isOpera) {
-                       this.iframe.startListening();
-               }
                        // Add unload handler
                var iframe = this.iframe.getEl().dom;
                Ext.EventManager.on(iframe.contentWindow ? iframe.contentWindow : iframe.contentDocument, 'unload', this.onUnload, this, {single: true});
@@ -2380,13 +2418,13 @@ HTMLArea.Editor = Ext.extend(Ext.util.Observable, {
                        }, false);
                }
                        // Cleanup
-               Ext.TaskMgr.stopAll();
+               Ext.TaskManager.stopAll();
                        // ExtJS is not releasing any resources when the iframe is unloaded
                this.htmlArea.destroy();
                Ext.iterate(this.plugins, function (pluginId) {
                        this.unRegisterPlugin(pluginId);
                }, this);
-               this.purgeListeners();
+               this.clearListeners();
                        // Cleaning references to DOM in order to avoid IE memory leaks
                if (this.wizards) {
                        this.wizards.dom = null;
@@ -2397,10 +2435,14 @@ HTMLArea.Editor = Ext.extend(Ext.util.Observable, {
                RTEarea[this.editorId].editor = null;
        }
 });
-HTMLArea.Ajax = function (config) {
-       Ext.apply(this, config);
-};
-HTMLArea.Ajax = Ext.extend(HTMLArea.Ajax, {
+HTMLArea.Ajax = Ext.define('HTMLArea.Ajax', {
+       /*
+        * Constructor
+        */
+       constructor: function (config) {
+               this.initConfig(config);
+               return this;
+       },
        /*
         * Load a Javascript file asynchronously
         *
@@ -3403,21 +3445,25 @@ HTMLArea.DOM.Walker = Ext.extend(HTMLArea.DOM.Walker, {
 /***************************************************
  *  HTMLArea.CSS.Parser: CSS Parser
  ***************************************************/
-HTMLArea.CSS.Parser = Ext.extend(Ext.util.Observable, {
+Ext.define('HTMLArea.CSS.Parser', {
+       extend: 'Ext.util.Observable',
+       /*
+        * Default config
+        */
+       config: {
+               parseAttemptsMaximumNumber: 20,
+               prefixLabelWithClassName: false,
+               postfixLabelWithClassName: false,
+               showTagFreeClasses: false,
+               tags: null,
+               editor: null
+       },
        /*
         * HTMLArea.CSS.Parser constructor
         */
        constructor: function (config) {
-               HTMLArea.CSS.Parser.superclass.constructor.call(this, {});
-               var configDefaults = {
-                       parseAttemptsMaximumNumber: 20,
-                       prefixLabelWithClassName: false,
-                       postfixLabelWithClassName: false,
-                       showTagFreeClasses: false,
-                       tags: null,
-                       editor: null
-               };
-               Ext.apply(this, config, configDefaults);
+               this.callParent([{}]);
+               this.initConfig(config);
                if (this.editor.config.styleSheetsMaximumAttempts) {
                        this.parseAttemptsMaximumNumber = this.editor.config.styleSheetsMaximumAttempts;
                }
@@ -3428,6 +3474,7 @@ HTMLArea.CSS.Parser = Ext.extend(Ext.util.Observable, {
                         */
                        'HTMLAreaEventCssParsingComplete'
                );
+               return this;
        },
        /*
         * The parsed classes
@@ -3498,7 +3545,7 @@ HTMLArea.CSS.Parser = Ext.extend(Ext.util.Observable, {
                                        this.fireEvent('HTMLAreaEventCssParsingComplete');
                                } else if (this.parseAttemptsCounter < this.parseAttemptsMaximumNumber) {
                                        this.parseAttemptsCounter++;
-                                       this.attemptTimeout = this.parse.defer(200, this);
+                                       this.attemptTimeout = Ext.Function.defer(this.parse, 200, this);
                                } else {
                                        this.editor.appendToLog('HTMLArea.CSS.Parser', 'parse', 'The stylesheets could not be parsed. Reported error: ' + this.error, 'error');
                                        this.fireEvent('HTMLAreaEventCssParsingComplete');
@@ -3746,7 +3793,7 @@ HTMLArea.CSS.Parser = Ext.extend(Ext.util.Observable, {
  *  TIPS ON FORM FIELDS AND MENU ITEMS
  ***************************************************/
 /*
- * Intercept Ext.form.Field.afterRender in order to provide tips on form fields and menu items
+ * Intercept Ext.form.field.Field.afterRender in order to provide tips on form fields
  * Adapted from: http://www.extjs.com/forum/showthread.php?t=36642
  */
 HTMLArea.util.Tips = function () {
@@ -3765,7 +3812,7 @@ HTMLArea.util.Tips = function () {
                                                style: 'vertical-align: middle; padding-right: 2px;'
                                        });
                                        if (this.helpDisplay == 'image' || this.helpDisplay == 'both'){
-                                               Ext.QuickTips.register({
+                                               Ext.tip.QuickTipManager.register({
                                                        target: helpImage,
                                                        title: this.helpTitle,
                                                        text: this.helpText
@@ -3773,27 +3820,17 @@ HTMLArea.util.Tips = function () {
                                        }
                                }
                                if (this.helpDisplay == 'field' || this.helpDisplay == 'both'){
-                                       Ext.QuickTips.register({
+                                       Ext.tip.QuickTipManager.register({
                                                target: this,
                                                title: this.helpTitle,
                                                text: this.helpText
                                        });
                                }
                        }
-               },
-               tipsOnMenuItems: function () {
-                       if (this.helpText || this.helpTitle) {
-                               Ext.QuickTips.register({
-                                       target: this,
-                                       title: this.helpTitle,
-                                       text: this.helpText
-                               });
-                       }
                }
        }
 }();
-Ext.form.Field.prototype.afterRender = Ext.form.Field.prototype.afterRender.createInterceptor(HTMLArea.util.Tips.tipsOnFormFields);
-Ext.menu.BaseItem.prototype.afterRender = Ext.menu.BaseItem.prototype.afterRender.createInterceptor(HTMLArea.util.Tips.tipsOnMenuItems);
+Ext.form.field.Field.prototype.afterRender = Ext.Function.createInterceptor(Ext.form.field.Field.prototype.afterRender, HTMLArea.util.Tips.tipsOnFormFields);
 /***************************************************
  *  COLOR WIDGETS AND UTILITIES
  ***************************************************/
@@ -3815,7 +3852,7 @@ HTMLArea.util.Color = function () {
                 * Returns hexadecimal color representation from a number or a rgb-style color.
                 */
                colorToHex: function(v) {
-                       if (!v) {
+                       if (!v && v !== 0) {
                                return '';
                        }
                        function hex(d) {
@@ -3841,60 +3878,68 @@ HTMLArea.util.Color = function () {
                                return v;
                        }
                        return null;
-               },
-               /*
-                * Select interceptor to ensure that the color exists in the palette before trying to select
-                */
-               checkIfColorInPalette: function (color) {
-                               // Do not continue if the new color is not in the palette
-                       if (this.el && !this.el.child('a.color-' + color)) {
-                                       // Remove any previous selection
-                               this.deSelect();
-                               return false;
-                       }
                }
        }
 }();
 /*
- * Intercept Ext.ColorPalette.prototype.select
+ * Intercept select method of Ext.picker.Color to ensure that the color exists in the palette before trying to select
  */
-Ext.ColorPalette.prototype.select = Ext.ColorPalette.prototype.select.createInterceptor(HTMLArea.util.Color.checkIfColorInPalette);
+Ext.picker.Color.prototype.select = Ext.Function.createInterceptor(Ext.picker.Color.prototype.select, function (color) {
+               // Do not continue if the new color is not in the palette
+       if (this.el && !this.el.down('a.color-' + color)) {
+                       // Remove any previous selection
+               this.deSelect();
+               return false;
+       }
+});
 /*
- * Add deSelect method to Ext.ColorPalette
+ * Add deSelect method to Ext.picker.Color
  */
-Ext.override(Ext.ColorPalette, {
+Ext.override(Ext.picker.Color, {
        deSelect: function () {
-               if (this.el && this.value){
-                       this.el.child('a.color-' + this.value).removeClass('x-color-palette-sel');
+               if (this.el && this.getValue()){
+                       this.el.down('a.color-' + this.getValue()).removeCls(this.selectedCls);
                        this.value = null;
                }
        }
 });
-Ext.ux.menu.HTMLAreaColorMenu = Ext.extend(Ext.menu.Menu, {
+Ext.define('HTMLArea.color.Menu', {
+       extend: 'Ext.menu.Menu',
+       alias: ['widget.htmlareacolormenu'],
        enableScrolling: false,
        hideOnClick: true,
-       cls: 'x-color-menu',
+       cls: 'htmlarea-color-menu',
        colorPaletteValue: '',
        customColorsValue: '',
+       layout: {
+               type: 'vbox',
+               align: 'center'
+       },
        plain: true,
        showSeparator: false,
        initComponent: function () {
                var paletteItems = [];
-               var width = 'auto';
                if (this.colorsConfiguration) {
                        paletteItems.push({
                                xtype: 'container',
-                               layout: 'anchor',
+                               cls: 'htmlarea-custom-colors-container',
+                               layout: 'fit',
                                width: 160,
-                               style: { float: 'right' },
                                items: {
-                                       xtype: 'colorpalette',
+                                       xtype: 'colorpicker',
                                        itemId: 'custom-colors',
                                        cls: 'htmlarea-custom-colors',
-                                       colors: this.colorsConfiguration,
+                                       data: this.colorsConfiguration,
                                        value: this.value,
                                        allowReselect: true,
-                                       tpl: new Ext.XTemplate(
+                                       listeners: {
+                                               afterrender: {
+                                                       fn: this.initRelay,
+                                                       scope: this,
+                                                       single: true
+                                               }
+                                       },
+                                       tpl: Ext.create('Ext.XTemplate',
                                                '<tpl for="."><a href="#" class="color-{1}" hidefocus="on"><em><span style="background:#{1}" unselectable="on">&#160;</span></em><span unselectable="on">{0}</span></a></tpl>'
                                        )
                                }
@@ -3903,54 +3948,52 @@ Ext.ux.menu.HTMLAreaColorMenu = Ext.extend(Ext.menu.Menu, {
                if (this.colors.length) {
                        paletteItems.push({
                                xtype: 'container',
-                               layout: 'anchor',
+                               layout: 'fit',
                                items: {
-                                       xtype: 'colorpalette',
+                                       xtype: 'colorpicker',
                                        itemId: 'color-palette',
                                        cls: 'color-palette',
                                        colors: this.colors,
                                        value: this.value,
-                                       allowReselect: true
+                                       allowReselect: true,
+                                       listeners: {
+                                               afterrender: {
+                                                       fn: this.initRelay,
+                                                       scope: this,
+                                                       single: true
+                                               }
+                                       }
                                }
                        });
                }
-               if (this.colorsConfiguration && this.colors.length) {
-                       width = 350;
-               }
                Ext.apply(this, {
-                       layout: 'menu',
-                       width: width,
                        items: paletteItems
                });
-               Ext.ux.menu.HTMLAreaColorMenu.superclass.initComponent.call(this);
-               this.standardPalette = this.find('itemId', 'color-palette')[0];
-               this.customPalette = this.find('itemId', 'custom-colors')[0];
-               if (this.standardPalette) {
-                       this.standardPalette.purgeListeners();
-                       this.relayEvents(this.standardPalette, ['select']);
-               }
-               if (this.customPalette) {
-                       this.customPalette.purgeListeners();
-                       this.relayEvents(this.customPalette, ['select']);
-               }
+               this.callParent(arguments);
                this.on('select', this.menuHide, this);
                if (this.handler){
                        this.on('select', this.handler, this.scope || this);
                }
        },
+       initRelay: function (colorPicker) {
+               this.relayEvents(colorPicker, ['select']);
+       },
        menuHide: function() {
                if (this.hideOnClick){
                        this.hide(true);
                }
        }
 });
-Ext.reg('htmlareacolormenu', Ext.ux.menu.HTMLAreaColorMenu);
+
 /*
- * Color palette trigger field
+ * Color picker trigger field
  * Based on http://www.extjs.com/forum/showthread.php?t=89312
  */
-Ext.ux.form.ColorPaletteField = Ext.extend(Ext.form.TriggerField, {
-       triggerClass: 'x-form-color-trigger',
+Ext.define('HTMLArea.color.Field', {
+       extend: 'Ext.form.field.Trigger',
+       alias: ['widget.colorpalettefield'],
+
+       triggerCls: 'htmlarea-form-color-trigger',
        defaultColors: [
                '000000', '222222', '444444', '666666', '999999', 'BBBBBB', 'DDDDDD', 'FFFFFF',
                '660000', '663300', '996633', '003300', '003399', '000066', '330066', '660066',
@@ -3968,7 +4011,7 @@ Ext.ux.form.ColorPaletteField = Ext.extend(Ext.form.TriggerField, {
        colorizeTrigger: false,
        editable: true,
        initComponent: function () {
-               Ext.ux.form.ColorPaletteField.superclass.initComponent.call(this);
+               this.callParent(arguments);
                if (!this.colors) {
                        this.colors = this.defaultColors;
                }
@@ -3983,21 +4026,21 @@ Ext.ux.form.ColorPaletteField = Ext.extend(Ext.form.TriggerField, {
        setValue: function (color) {
                if (color) {
                        if (this.colorizeFieldBackgroud) {
-                               this.el.applyStyles('background: #' + color  + ';');
+                               this.inputEl.applyStyles('background: #' + color  + ';');
                        }
                        if (this.colorizeFieldText) {
-                               this.el.applyStyles('color: #' + this.rgbToHex(this.invert(this.hexToRgb(color)))  + ';');
+                               this.inputEl.applyStyles('color: #' + this.rgbToHex(this.invert(this.hexToRgb(color)))  + ';');
                        }
                        if (this.colorizeTrigger) {
-                               this.trigger.applyStyles('background-color: #' + color  + ';');
+                               this.triggerEl.applyStyles('background-color: #' + color  + ';');
                        }
                }
-               return Ext.ux.form.ColorPaletteField.superclass.setValue.call(this, color);
+               return this.callParent(arguments);
        },
                // private
        onDestroy: function () {
                Ext.destroy(this.menu);
-               Ext.ux.form.ColorPaletteField.superclass.onDestroy.call(this);
+               this.callParent(arguments);
        },
                // private
        onTriggerClick: function () {
@@ -4005,7 +4048,7 @@ Ext.ux.form.ColorPaletteField = Ext.extend(Ext.form.TriggerField, {
                        return;
                }
                if (this.menu == null) {
-                       this.menu = new Ext.ux.menu.HTMLAreaColorMenu({
+                       this.menu = Ext.create('HTMLArea.color.Menu', {
                                cls: 'htmlarea-color-menu',
                                hideOnClick: false,
                                colors: this.colors,
@@ -4059,7 +4102,7 @@ Ext.ux.form.ColorPaletteField = Ext.extend(Ext.form.TriggerField, {
                return HCHARS.charAt( ( n - n % 16 ) / 16 ) + HCHARS.charAt( n % 16 );
        }
 });
-Ext.reg('colorpalettefield', Ext.ux.form.ColorPaletteField);
+
 /**
  * Internet Explorer returns an item having the _name_ equal to the given id, even if it's not having any id.
  * This way it can return a different form field even if it's not a textarea.  This works around the problem by
@@ -4095,10 +4138,10 @@ HTMLArea.initEditor = function(editorNumber) {
                        document.getElementById('pleasewait' + editorNumber).style.display = 'block';
                        document.getElementById('editorWrap' + editorNumber).style.visibility = 'hidden';
                        if (!HTMLArea.isReady) {
-                               HTMLArea.initEditor.defer(150, null, [editorNumber]);
+                               Ext.Function.defer(HTMLArea.initEditor, 150, null, [editorNumber]);
                        } else {
                                        // Create an editor for the textarea
-                               var editor = new HTMLArea.Editor(Ext.apply(new HTMLArea.Config(editorNumber), RTEarea[editorNumber]));
+                               var editor = Ext.create('HTMLArea.Editor', Ext.apply(Ext.create('HTMLArea.Config', editorNumber), RTEarea[editorNumber]));
                                editor.generate();
                                return false;
                        }
@@ -4114,21 +4157,15 @@ HTMLArea.initEditor = function(editorNumber) {
  * Every plugin should be a subclass of this class
  *
  */
-HTMLArea.Plugin = function (editor, pluginName) {
-};
-/**
- ***********************************************
- * THIS FUNCTION IS DEPRECATED AS OF TYPO3 4.6 *
- ***********************************************
- * Extends class HTMLArea.Plugin
- *
- * Defined for backward compatibility only
- * Use Ext.extend(SubClassName, config) directly
- */
-HTMLArea.Plugin.extend = function (config) {
-       return Ext.extend(HTMLArea.Plugin, config);
-};
-HTMLArea.Plugin = Ext.extend(HTMLArea.Plugin, {
+Ext.define('HTMLArea.Plugin', {
+       /*
+        * Reference to the editor instance
+        */
+       editor: null,
+       /*
+        * Name of the plugin
+        */
+       name: 'unknown',
        /**
         * HTMLArea.Plugin constructor
         *
@@ -4149,18 +4186,7 @@ HTMLArea.Plugin = Ext.extend(HTMLArea.Plugin, {
                        this.I18N = new Object();
                }
                this.configurePlugin(editor);
-               /**
-                ***********************************************
-                * THIS FUNCTION IS DEPRECATED AS OF TYPO3 4.6 *
-                ***********************************************
-                * Extends class HTMLArea[pluginName]
-                *
-                * Defined for backward compatibility only
-                * Use Ext.extend(SubClassName, config) directly
-                */
-               HTMLArea[pluginName].extend = function (config) {
-                       return Ext.extend(HTMLArea[pluginName], config);
-               };
+               return this;
        },
        /**
         * Configures the plugin
@@ -4181,7 +4207,7 @@ HTMLArea.Plugin = Ext.extend(HTMLArea.Plugin, {
         ***********************************************
         * THIS FUNCTION IS DEPRECATED AS OF TYPO3 4.6 *
         ***********************************************
-        * Invove the base class constructor
+        * Invoke the base class constructor
         *
         * Defined for backward compatibility only
         * Note: this.base will exclusively refer to the HTMLArea.Plugin class constructor
@@ -4220,7 +4246,7 @@ HTMLArea.Plugin = Ext.extend(HTMLArea.Plugin, {
         *
         * @return      object          the plugin information object
         */
-       getPluginInformation : function() {
+       getPluginInformation: function() {
                return this.pluginInformation;
        },
 
@@ -4230,7 +4256,7 @@ HTMLArea.Plugin = Ext.extend(HTMLArea.Plugin, {
         * @param       string          pluinName: the name of some plugin
         * @return      object          the plugin object or null
         */
-       getPluginInstance : function(pluginName) {
+       getPluginInstance: function(pluginName) {
                return this.editor.getPlugin(pluginName);
        },
 
@@ -4239,7 +4265,7 @@ HTMLArea.Plugin = Ext.extend(HTMLArea.Plugin, {
         *
         * @return      string          editor mode
         */
-       getEditorMode : function() {
+       getEditorMode: function() {
                return this.editor.getMode();
        },
 
@@ -4250,7 +4276,7 @@ HTMLArea.Plugin = Ext.extend(HTMLArea.Plugin, {
         *
         * @return      boolean         true if the button is enabled in the toolbar configuration
         */
-       isButtonInToolbar : function(buttonId) {
+       isButtonInToolbar: function(buttonId) {
                var index = -1;
                Ext.each(this.editorConfiguration.toolbar, function (row) {
                        Ext.each(row, function (group) {
@@ -4387,7 +4413,7 @@ HTMLArea.Plugin = Ext.extend(HTMLArea.Plugin, {
         *
         * @return      object          the drop-down configuration object
         */
-       getDropDownConfiguration : function(dropDownId) {
+       getDropDownConfiguration: function(dropDownId) {
                return this.editorConfiguration.buttonsConfig[dropDownId];
        },
 
@@ -4401,7 +4427,7 @@ HTMLArea.Plugin = Ext.extend(HTMLArea.Plugin, {
         *
         * @return      boolean         true if the hotkey was successfully registered
         */
-       registerHotKey : function (hotKeyConfiguration) {
+       registerHotKey: function (hotKeyConfiguration) {
                return this.editorConfiguration.registerHotKey(hotKeyConfiguration);
        },
 
@@ -4412,7 +4438,7 @@ HTMLArea.Plugin = Ext.extend(HTMLArea.Plugin, {
         *
         * @return      string          the buttonId or ""
         */
-       translateHotKey : function(key) {
+       translateHotKey: function(key) {
                if (typeof(this.editorConfiguration.hotKeyList[key]) !== "undefined") {
                        var buttonId = this.editorConfiguration.hotKeyList[key].cmd;
                        if (typeof(buttonId) !== "undefined") {
@@ -4440,7 +4466,7 @@ HTMLArea.Plugin = Ext.extend(HTMLArea.Plugin, {
        },
        /**
         * Initializes the plugin
-        * Is invoked when the toolbar component is created (subclass of Ext.ux.HTMLAreaButton or Ext.ux.form.HTMLAreaCombo)
+        * Is invoked when the toolbar component is created (subclass of HTMLArea.toolbar.Button or HTMLArea.toolbar.ComboBox)
         *
         * @param       object          button: the component
         *
@@ -4545,21 +4571,17 @@ HTMLArea.Plugin = Ext.extend(HTMLArea.Plugin, {
         * @ return     void
         */
        openContainerWindow: function (buttonId, title, dimensions, url) {
-               this.dialog = new Ext.Window({
+               this.dialog = Ext.create('Ext.window.Window', {
+                       border: false,
+                       cls: 'htmlarea-window',
+                       height: dimensions.height,
+                       iconCls: this.getButton(buttonId).iconCls,
                        id: this.editor.editorId + buttonId,
+                       layout: 'fit',
+                       resizable: true,
                        title: this.localize(title) || title,
-                       cls: 'htmlarea-window',
                        width: dimensions.width,
-                       border: false,
-                       resizable: true,
-                       iconCls: this.getButton(buttonId).iconCls,
                        listeners: {
-                               afterrender: {
-                                       fn: this.onContainerResize
-                               },
-                               resize: {
-                                       fn: this.onContainerResize
-                               },
                                close: {
                                        fn: this.onClose,
                                        scope: this
@@ -4567,7 +4589,7 @@ HTMLArea.Plugin = Ext.extend(HTMLArea.Plugin, {
                        },
                        items: {
                                        // The content iframe
-                               xtype: 'box',
+                               xtype: 'component',
                                height: dimensions.height-20,
                                itemId: 'content-iframe',
                                autoEl: {
@@ -4580,15 +4602,6 @@ HTMLArea.Plugin = Ext.extend(HTMLArea.Plugin, {
                this.show();
        },
        /*
-        * Handler invoked when the container window is rendered or resized in order to resize the content iframe to maximum size
-        */
-       onContainerResize: function (panel) {
-               var iframe = panel.getComponent('content-iframe');
-               if (iframe.rendered) {
-                       iframe.getEl().setSize(panel.getInnerWidth(), panel.getInnerHeight());
-               }
-       },
-       /*
         * Get the opening diment=sions of the window
         *
         * @param       object          dimensions: default opening width and height set by the plugin
@@ -4656,18 +4669,11 @@ HTMLArea.Plugin = Ext.extend(HTMLArea.Plugin, {
                }
        },
        /*
-        * Handler for Ext.TabPanel tabchange event
-        * Force window ghost height synchronization
-        * Working around ExtJS 3.1 bug
-        */
-       syncHeight: function (tabPanel, tab) {
-               var position = this.dialog.getPosition();
-               if (position[0] > 0) {
-                       this.dialog.setPosition(position);
-               }
-       },
-       /*
         * Show the dialogue window
+        *
+        * We cannot use autoShow on dialogue windows:
+        *      - we want to close the window if the editor changes mode
+        *      - we need to save and restore the selection for IE which looses it when focus leaves the iframe
         */
        show: function () {
                        // Close the window if the editor changes mode
index e45b28c..50e4f3a 100644 (file)
 /*
  * About Plugin for TYPO3 htmlArea RTE
  */
-HTMLArea.AboutEditor = Ext.extend(HTMLArea.Plugin, {
+/*
+ * Define data model for editor plugins data
+ */
+Ext.define('HTMLArea.model.AboutEditor', {
+       extend: 'Ext.data.Model',
+       fields: [{
+                       name: 'name',
+                       type: 'string'
+               },{
+                       name: 'developer',
+                       type: 'string'
+               },{
+                       name: 'sponsor',
+                       type: 'string'
+       }]
+});
+/*
+ * Define AboutEditor plugin
+ */
+Ext.define('HTMLArea.AboutEditor', {
+       extend: 'HTMLArea.Plugin',
        /*
         * This function gets called by the class constructor
         */
@@ -38,7 +58,7 @@ HTMLArea.AboutEditor = Ext.extend(HTMLArea.Plugin, {
                 * Registering plugin "About" information
                 */
                var pluginInformation = {
-                       version         : '2.1',
+                       version         : '3.0',
                        developer       : 'Stanislas Rolland',
                        developerUrl    : 'http://www.sjbr.ca/',
                        copyrightOwner  : 'Stanislas Rolland',
@@ -88,7 +108,13 @@ HTMLArea.AboutEditor = Ext.extend(HTMLArea.Plugin, {
                this.openDialogue(
                        buttonId,
                        'About HTMLArea',
-                       this.getWindowDimensions({width:450, height:350}, buttonId),
+                       this.getWindowDimensions(
+                               {
+                                       width: 480,
+                                       height: 350
+                               },
+                               buttonId
+                       ),
                        this.buildTabItems()
                );
                return false;
@@ -104,14 +130,13 @@ HTMLArea.AboutEditor = Ext.extend(HTMLArea.Plugin, {
         * @return      void
         */
        openDialogue: function (buttonId, title, dimensions, tabItems) {
-               this.dialog = new Ext.Window({
+               this.dialog = Ext.create('Ext.window.Window', {
                        title: this.localize(title),
                        cls: 'htmlarea-window',
                        border: false,
                        width: dimensions.width,
-                       height: 'auto',
-                               // As of ExtJS 3.1, JS error with IE when the window is resizable
-                       resizable: !Ext.isIE,
+                       layout: 'anchor',
+                       resizable: true,
                        iconCls: this.getButton(buttonId).iconCls,
                        listeners: {
                                close: {
@@ -126,10 +151,6 @@ HTMLArea.AboutEditor = Ext.extend(HTMLArea.Plugin, {
                                        activate: {
                                                fn: this.resetFocus,
                                                scope: this
-                                       },
-                                       tabchange: {
-                                               fn: this.syncHeight,
-                                               scope: this
                                        }
                                },
                                items: tabItems
@@ -150,7 +171,7 @@ HTMLArea.AboutEditor = Ext.extend(HTMLArea.Plugin, {
                        // About tab
                tabItems.push({
                        xtype: 'panel',
-                       cls: 'about',
+                       bodyCls: 'htmlarea-about',
                        title: this.localize('About'),
                        html: '<h1 id="version">htmlArea RTE ' +  RTEarea[0].version + '</h1>'
                                + '<p>' + this.localize('free_editor').replace('<', '&lt;').replace('>', '&gt;') + '</p>'
@@ -160,44 +181,47 @@ HTMLArea.AboutEditor = Ext.extend(HTMLArea.Plugin, {
                                        + '<br />'
                                        + '&copy; 2002-2004 <a href="http://interactivetools.com" target="_blank">interactivetools.com, inc.</a><br />'
                                        + '&copy; 2003-2004 <a href="http://dynarch.com" target="_blank">dynarch.com LLC.</a><br />'
-                                       + '&copy; 2004-2010 <a href="http://www.sjbr.ca" target="_blank">Stanislas Rolland</a><br />'
+                                       + '&copy; 2004-2011 <a href="http://www.sjbr.ca" target="_blank">Stanislas Rolland</a><br />'
                                        + this.localize('All rights reserved.')
                                + '</p>'
                });
-                       // Plugins tab
-               if (!this.store) {
-                       this.store = new Ext.data.ArrayStore({
-                               fields: [{ name: 'name'}, { name: 'developer'},  { name: 'sponsor'}],
-                               sortInfo: {
-                                       field: 'name',
-                                       direction: 'ASC'
-                               },
-                               data: this.getPluginsInfo()
+                       // Create pluginInfo global store
+               var pluginInfoStore = Ext.data.StoreManager.lookup('HTMLArea' + '-store-' + this.name + 'pluginInfo');
+               if (!pluginInfoStore) {
+                       pluginInfoStore = Ext.create('Ext.data.ArrayStore', {
+                               model: 'HTMLArea.model.AboutEditor',
+                               sorters: [{
+                                           property: 'name',
+                                           direction: 'ASC'
+                               }],
+                               storeId: 'HTMLArea' + '-store-' + this.name + 'pluginInfo'
                        });
+                       pluginInfoStore.loadData(this.getPluginsInfo());
                }
                tabItems.push({
-                       xtype: 'panel',
-                       cls: 'about-plugins',
-                       height: 200,
+                       xtype: 'grid',
+                       cls: 'htmlarea-about-plugins',
+                       height: 300,
                        title: this.localize('Plugins'),
+                       store: pluginInfoStore,
                        autoScroll: true,
-                       items: {
-                               xtype: 'listview',
-                               store: this.store,
-                               reserveScrollOffset: true,
-                               columns: [{
+                       columns: [{
                                        header: this.localize('Name'),
                                        dataIndex: 'name',
-                                       width: .33
+                                       hideable: false,
+                                       width: 150
                                    },{
                                        header: this.localize('Developer'),
                                        dataIndex: 'developer',
-                                       width: .33
+                                       hideable: false,
+                                       width: 150
                                    },{
                                        header: this.localize('Sponsored by'),
-                                       dataIndex: 'sponsor'
-                               }]
-                       }
+                                       dataIndex: 'sponsor',
+                                       hideable: false,
+                                       width: 150
+                                   }
+                       ]
                });
                return tabItems;
        },
@@ -209,11 +233,11 @@ HTMLArea.AboutEditor = Ext.extend(HTMLArea.Plugin, {
        getPluginsInfo: function () {
                var pluginsInfo = [];
                Ext.iterate(this.editor.plugins, function (pluginId, plugin) {
-                       pluginsInfo.push([
-                               plugin.name + ' ' + plugin.version,
-                               '<a href="' + plugin.developerUrl + '" target="_blank">' + plugin.developer + '</a>',
-                               '<a href="' + plugin.sponsorUrl + '" target="_blank">' + plugin.sponsor + '</a>'
-                       ]);
+                       pluginsInfo.push({
+                               name: plugin.name + ' ' + plugin.version,
+                               developer: '<a href="' + plugin.developerUrl + '" target="_blank">' + plugin.developer + '</a>',
+                               sponsor: '<a href="' + plugin.sponsorUrl + '" target="_blank">' + plugin.sponsor + '</a>'
+                       });
                }, this);
                return pluginsInfo;
        }
index 1f27517..ad6a129 100644 (file)
 /*
  * Acronym plugin for htmlArea RTE
  */
-HTMLArea.Acronym = Ext.extend(HTMLArea.Plugin, {
+/*
+ * Define data model for abbreviation data
+ */
+Ext.define('HTMLArea.model.Abbreviation', {
+       extend: 'Ext.data.Model',
+       fields: [{
+                       name: 'term',
+                       type: 'string'
+               },{
+                       name: 'abbr',
+                       type: 'string'
+               },{
+                       name: 'language',
+                       type: 'string'
+       }]
+});
+/*
+ * Define Acronym plugin
+ */
+Ext.define('HTMLArea.Acronym', {
+       extend: 'HTMLArea.Plugin',
        /*
         * This function gets called by the class constructor
         */
@@ -37,7 +57,7 @@ HTMLArea.Acronym = Ext.extend(HTMLArea.Plugin, {
                 * Registering plugin "About" information
                 */
                var pluginInformation = {
-                       version         : '2.4',
+                       version         : '3.0',
                        developer       : 'Stanislas Rolland',
                        developerUrl    : 'http://www.sjbr.ca/',
                        copyrightOwner  : 'Stanislas Rolland',
@@ -66,13 +86,15 @@ HTMLArea.Acronym = Ext.extend(HTMLArea.Plugin, {
         * Sets of default configuration values for dialogue form fields
         */
        configDefaults: {
-               combo: {
+               combobox: {
+                       cls: 'htmlarea-combo',
                        editable: true,
+                       forceSelection: true,
+                       queryMode: 'local',
                        selectOnFocus: true,
-                       typeAhead: true,
                        triggerAction: 'all',
-                       forceSelection: true,
-                       mode: 'local'
+                       typeAhead: true,
+                       xtype: 'combobox'
                }
        },
        /*
@@ -104,7 +126,7 @@ HTMLArea.Acronym = Ext.extend(HTMLArea.Plugin, {
                };
                        // Open the dialogue window
                this.openDialogue(
-                       this.getButton(buttonId).tooltip.title,
+                       this.getButton(buttonId).tooltip.text,
                        buttonId,
                        this.getWindowDimensions({ width: 580}, buttonId),
                        this.buildTabItemsConfig(abbr),
@@ -126,14 +148,13 @@ HTMLArea.Acronym = Ext.extend(HTMLArea.Plugin, {
         * @return      void
         */
        openDialogue: function (title, buttonId, dimensions, tabItems, buttonsConfig, activeTab) {
-               this.dialog = new Ext.Window({
+               this.dialog = Ext.create('Ext.window.Window', {
                        title: this.getHelpTip('', title),
                        cls: 'htmlarea-window',
-                               // As of ExtJS 3.1, JS error with IE when the window is resizable
-                       resizable: !Ext.isIE,
                        border: false,
                        width: dimensions.width,
-                       height: 'auto',
+                       layout: 'anchor',
+                       resizable: true,
                        iconCls: this.getButton(buttonId).iconCls,
                        listeners: {
                                close: {
@@ -141,24 +162,18 @@ HTMLArea.Acronym = Ext.extend(HTMLArea.Plugin, {
                                        scope: this
                                }
                        },
-                       items: {
+                       items: [{
                                xtype: 'tabpanel',
                                activeTab: activeTab ? activeTab : 0,
                                defaults: {
                                        xtype: 'container',
-                                       layout: 'form',
+                                       layout: 'anchor',
                                        defaults: {
                                                labelWidth: 150
                                        }
                                },
-                               listeners: {
-                                       tabchange: {
-                                               fn: this.syncHeight,
-                                               scope: this
-                                       }
-                               },
                                items: tabItems
-                       },
+                       }],
                        buttons: buttonsConfig
                });
                this.show();
@@ -230,125 +245,132 @@ HTMLArea.Acronym = Ext.extend(HTMLArea.Plugin, {
         * @return      object          the fieldset configuration object
         */
        buildDefinedTermFieldsetConfig: function (element, type) {
+                       // Create global abbreviation store if it does not exist already
+               var abbreviationStore = Ext.data.StoreManager.lookup(this.editorId + '-store-' + this.name);
+               if (!abbreviationStore) {
+                       this.abbreviationStore = Ext.create('Ext.data.Store', {
+                               autoLoad: true,
+                               model: 'HTMLArea.model.Abbreviation',
+                               proxy: {
+                                       type: 'ajax',
+                                       url: this.pageTSConfiguration.acronymUrl,
+                                       reader: {
+                                               type: 'json',
+                                               root: type
+                                       }
+                               },
+                               storeId: this.editorId + '-store-' + this.name
+                       });
+               }
                var itemsConfig = [];
-               itemsConfig.push(Ext.apply({
-                       xtype: 'combo',
+               itemsConfig.push(Ext.applyIf({
                        displayField: 'term',
-                       valueField: 'term',
                        fieldLabel: this.getHelpTip('unabridgedTerm', 'Unabridged_term'),
+                       listConfig: {
+                               cls: 'htmlarea-combo-list',
+                               getInnerTpl: function () {
+                                       return '<div data-qtip="{abbr}" class="htmlarea-combo-list-item">{term}</div>';
+                               },
+                       },
                        itemId: 'termSelector',
-                       tpl: '<tpl for="."><div ext:qtip="{abbr}" style="text-align:left;font-size:11px;" class="x-combo-list-item">{term}</div></tpl>',
-                       store: new Ext.data.JsonStore({
-                               autoDestroy:  true,
-                               autoLoad: true,
-                               root: type,
-                               fields: [ { name: 'term'}, { name: 'abbr'},  { name: 'language'}],
-                               url: this.pageTSConfiguration.acronymUrl
-                       }),
-                       width: 350,
                        listeners: {
-                               beforerender: {
-                                       fn: function (combo) {
-                                                       // Ensure the store is loaded
-                                               combo.getStore().load({
-                                                       callback: function () { this.onSelectorRender(combo); },
-                                                       scope: this
-                                               });
-                                       },
-                                       scope: this
-                               },
                                select: {
                                        fn: this.onTermSelect,
                                        scope: this
                                }
-                       }
-               }, this.configDefaults['combo']));
-               itemsConfig.push(Ext.apply({
-                       xtype: 'combo',
+                       },
+                       store: this.abbreviationStore,
+                       valueField: 'term',
+                       width: 350
+               }, this.configDefaults['combobox']));
+               itemsConfig.push(Ext.applyIf({
                        displayField: 'abbr',
-                       valueField: 'abbr',
-                       tpl: '<tpl for="."><div ext:qtip="{language}" style="text-align:left;font-size:11px;" class="x-combo-list-item">{abbr}</div></tpl>',
                        fieldLabel: this.getHelpTip('abridgedTerm', 'Abridged_term'),
+                       listConfig: {
+                               cls: 'htmlarea-combo-list',
+                               getInnerTpl: function () {
+                                       return '<div data-qtip="{language}" class="htmlarea-combo-list-item">{abbr}</div>';
+                               }
+                       },
                        itemId: 'abbrSelector',
-                       store: new Ext.data.JsonStore({
-                               autoDestroy:  true,
-                               autoLoad: true,
-                               root: type,
-                               fields: [ { name: 'term'}, { name: 'abbr'},  { name: 'language'}],
-                               url: this.pageTSConfiguration.acronymUrl
-                       }),
-                       width: 100,
                        listeners: {
-                               beforerender: {
-                                       fn: function (combo) {
-                                                       // Ensure the store is loaded
-                                               combo.getStore().load({
-                                                       callback: function () { this.onSelectorRender(combo); },
-                                                       scope: this
-                                               });
-                                       },
-                                       scope: this
-                               },
                                select: {
                                        fn: this.onAbbrSelect,
                                        scope: this
                                }
+                       },
+                       store: this.abbreviationStore,
+                       valueField: 'abbr',
+                       width: 200
+               }, this.configDefaults['combobox']));
+               var languagePlugin = this.getPluginInstance('Language');
+               if (this.getButton('Language') && languagePlugin) {
+                       var selectedLanguage = !Ext.isEmpty(element) ? languagePlugin.getLanguageAttribute(element) : 'none';
+                               // Create global language store if it does not exist already
+                       var languageStore = Ext.data.StoreManager.lookup(this.editorId + '-store-' + languagePlugin.name);
+                       if (!languageStore) {
+                               languageStore = Ext.create('Ext.data.Store', {
+                                       autoLoad: true,
+                                       model: 'HTMLArea.model.default',
+                                       proxy: {
+                                               type: 'ajax',
+                                               url: this.getDropDownConfiguration('Language').dataUrl,
+                                               reader: {
+                                                       type: 'json',
+                                                       root: 'options',
+                                               }
+                                       },
+                                       storeId: this.editorId + '-store-' + languagePlugin.name
+                               });
                        }
-               }, this.configDefaults['combo']));
-               var languageObject = this.getPluginInstance('Language');
-               if (this.getButton('Language')) {
-                       var selectedLanguage = !Ext.isEmpty(element) ? languageObject.getLanguageAttribute(element) : 'none';
-                       function initLanguageStore (store) {
-                               if (selectedLanguage !== 'none') {
-                                       store.removeAt(0);
-                                       store.insert(0, new store.recordType({
-                                               text: languageObject.localize('Remove language mark'),
-                                               value: 'none'
-                                       }));
-                               }
-                               this.getButton('Language').setValue('none');
-                       }
-                       var languageStore = new Ext.data.JsonStore({
-                               autoDestroy:  true,
-                               autoLoad: true,
-                               root: 'options',
-                               fields: [ { name: 'text'}, { name: 'value'} ],
-                               url: this.getDropDownConfiguration('Language').dataUrl,
-                               listeners: {
-                                       load: {
-                                               fn: initLanguageStore,
-                                               scope: this
-                                       }
-                               }
-                       });
                        itemsConfig.push(Ext.apply({
-                               xtype: 'combo',
+                               displayField: 'text',
                                fieldLabel: this.getHelpTip('language', 'Language'),
                                itemId: 'language',
-                               valueField: 'value',
-                               displayField: 'text',
-                               tpl: '<tpl for="."><div ext:qtip="{value}" style="text-align:left;font-size:11px;" class="x-combo-list-item">{text}</div></tpl>',
-                               store: languageStore,
-                               width: 200,
-                               value: selectedLanguage,
+                               listConfig: {
+                                       cls: 'htmlarea-combo-list',
+                                       getInnerTpl: function () {
+                                               return '<div data-qtip="{value}" class="htmlarea-combo-list-item">{text}</div>';
+                                       }
+                               },
                                listeners: {
-                                       render: {
+                                       afterrender: {
                                                fn: function (combo) {
-                                                               // Load the language dropdown
-                                                       combo.getStore().load({
-                                                               callback: function () { combo.setValue(selectedLanguage); }
-                                                       });
-                                               }
+                                                               // Somehow getStore method got lost...
+                                                       if (!Ext.isFunction(combo.getStore)) {
+                                                               combo.getStore = function () {
+                                                                       return combo.store;
+                                                               };
+                                                       }
+                                                       var store = combo.getStore();
+                                                       store.removeAt(0);
+                                                       if (selectedLanguage !== 'none') {
+                                                               store.insert(0, {
+                                                                       text: languagePlugin.localize('Remove language mark'),
+                                                                       value: 'none'
+                                                               });
+                                                       } else {
+                                                               store.insert(0, {
+                                                                       text: languagePlugin.localize('No language mark'),
+                                                                       value: 'none'
+                                                               });
+                                                       }
+                                                       combo.setValue(selectedLanguage);
+                                               },
+                                               scope: this
                                        }
-                               }
-                       }, this.configDefaults['combo']));
+                               },
+                               store: languageStore,
+                               valueField: 'value',
+                               width: 350
+                       }, this.configDefaults['combobox']));
                }
                return {
                        xtype: 'fieldset',
                        title: this.getHelpTip('preDefined' + ((type == 'abbr') ? 'Abbreviation' : 'Acronym'), 'Defined_' + type),
                        items: itemsConfig,
                        listeners: {
-                               render: {
+                               afterrender: {
                                        fn: this.onDefinedTermFieldsetRender,
                                        scope: this
                                }
@@ -357,15 +379,34 @@ HTMLArea.Acronym = Ext.extend(HTMLArea.Plugin, {
        },
        /*
         * Handler on rendering the defined abbreviation fieldset
-        * If an abbr is selected but no term is selected, select any corresponding term with the correct language value, if any
         */
        onDefinedTermFieldsetRender: function (fieldset) {
-               var termSelector = fieldset.find('itemId', 'termSelector')[0];
+                       // Make sure the store is loaded
+               if (!this.abbreviationStore.getCount()) {
+                       this.abbreviationStore.load({
+                               callback: function (records) {
+                                       this.abbreviationStore.savedSnapshot = this.abbreviationStore.data.clone();
+                                       this.initializeFieldset(fieldset);
+                               },
+                               scope: this
+                       });
+               } else {
+                               // Refresh the store
+                       this.abbreviationStore.snapshot = this.abbreviationStore.savedSnapshot.clone();
+                       this.initializeFieldset(fieldset);
+               }
+       },
+       /*
+        * Initialize fieldset
+        * If an abbr is selected but no term is selected, select any corresponding term with the correct language value, if any
+        */
+       initializeFieldset: function (fieldset) {
+               var termSelector = fieldset.getComponent('termSelector');
                var term = termSelector.getValue();
-               var abbrSelector = fieldset.find('itemId', 'abbrSelector')[0];
+               var abbrSelector = fieldset.getComponent('abbrSelector');
                var abbr = abbrSelector.getValue();
                var language = '';
-               var languageSelector = fieldset.find('itemId', 'language')[0];
+               var languageSelector = fieldset.down('combobox[itemId=language]');
                if (languageSelector) {
                        var language = languageSelector.getValue();
                        if (language == 'none') {
@@ -380,23 +421,34 @@ HTMLArea.Acronym = Ext.extend(HTMLArea.Plugin, {
                        if (index !== -1) {
                                term = abbrStore.getAt(index).get('term');
                                termSelector.setValue(term);
-                               fieldset.ownerCt.find('itemId', 'useTerm')[0].setValue(term);
+                               fieldset.ownerCt.down('component[itemId=useTerm]').setValue(term);
                        }
                }
+                       // Filter the abbreviation store
+               this.abbreviationStore.filterBy(function (record) {
+                       return !this.params.text
+                               || !this.params.title
+                               || this.params.text == record.get('term')
+                               || this.params.text == record.get('abbr')
+                               || this.params.title == record.get('term')
+                               || this.params.title == record.get('abbr');
+               }, this);
+                       // Make sure the combo lists are filtered
+               this.abbreviationStore.snapshot = this.abbreviationStore.data;
+               if (this.abbreviationStore.getCount()) {
+                               // Initialize combos
+                       this.initializeCombo(termSelector);
+                       this.initializeCombo(abbrSelector);
+               } else {
+                       fieldset.hide();
+               }
        },
        /*
-        * Filter the term and abbr selector lists
         * Set initial values
         * If there is already an abbr and the filtered list has only one or no element, hide the fieldset
         */
-       onSelectorRender: function (combo) {
-               var store = combo.getStore();
-               store.filterBy(function (record) {
-                       return !this.params.text || !this.params.title || this.params.text == record.get('term') || this.params.title == record.get('term') || this.params.title == record.get('abbr');
-               }, this);
-                       // Make sure the combo list is filtered
-               store.snapshot = store.data;
-               var store = combo.getStore();
+       initializeCombo: function (combo) {
+               var store = this.abbreviationStore;
                        // Initialize the term and abbr combos
                if (combo.getItemId() == 'termSelector') {
                        if (this.params.title) {
@@ -404,14 +456,14 @@ HTMLArea.Acronym = Ext.extend(HTMLArea.Plugin, {
                                if (index !== -1) {
                                        var record = store.getAt(index);
                                        combo.setValue(record.get('term'));
-                                       this.onTermSelect(combo, record, index);
+                                       this.onTermSelect(combo, [record], false);
                                }
                        } else if (this.params.text) {
                                var index = store.findExact('term', this.params.text);
                                if (index !== -1) {
                                        var record = store.getAt(index);
                                        combo.setValue(record.get('term'));
-                                       this.onTermSelect(combo, record, index);
+                                       this.onTermSelect(combo, [record], false);
                                }
                        }
                } else if (combo.getItemId() == 'abbrSelector' && this.params.text) {
@@ -419,56 +471,52 @@ HTMLArea.Acronym = Ext.extend(HTMLArea.Plugin, {
                        if (index !== -1) {
                                var record = store.getAt(index);
                                combo.setValue(record.get('abbr'));
-                               this.onAbbrSelect(combo, record, index);
+                               this.onAbbrSelect(combo, [record], false);
                        }
                }
        },
        /*
         * Handler when a term is selected
         */
-       onTermSelect: function (combo, record, index) {
+       onTermSelect: function (combo, records, options) {
+               var record = records[0];
                var fieldset = combo.findParentByType('fieldset');
                var tab = fieldset.findParentByType('container');
                var term = record.get('term');
                var abbr = record.get('abbr');
                var language = record.get('language');
                        // Update the abbreviation selector
-               var abbrSelector = tab.find('itemId', 'abbrSelector')[0];
-               abbrSelector.setValue(abbr);
+               tab.down('component[itemId=abbrSelector]').setValue(abbr);
                        // Update the language selector
-               var languageSelector = tab.find('itemId', 'language');
-               if (!Ext.isEmpty(languageSelector)) {
-                       if (language) {
-                               languageSelector[0].setValue(language);
-                       } else {
-                               languageSelector[0].setValue('none');
-                       }
+               var languageSelector = tab.down('combobox[itemId=language]');
+               if (!Ext.isEmpty(languageSelector) && !Ext.isBoolean(options)) {
+                       languageSelector.setValue(language ? language : 'none');
                }
                        // Update the term to use
-               tab.find('itemId', 'useTerm')[0].setValue(term);
+               if (!Ext.isBoolean(options)) {
+                       tab.down('component[itemId=useTerm]').setValue(term);
+               }
        },
        /*
         * Handler when an abbreviation or acronym is selected
         */
-       onAbbrSelect: function (combo, record, index) {
+       onAbbrSelect: function (combo, records, options) {
+               var record = records[0];
                var fieldset = combo.findParentByType('fieldset');
                var tab = fieldset.findParentByType('container');
                var term = record.get('term');
                var language = record.get('language');
                        // Update the term selector
-               var termSelector = tab.find('itemId', 'termSelector')[0];
-               termSelector.setValue(term);
+               tab.down('component[itemId=termSelector]').setValue(term);
                        // Update the language selector
-               var languageSelector = tab.find('itemId', 'language');
-               if (!Ext.isEmpty(languageSelector)) {
-                       if (language) {
-                               languageSelector[0].setValue(language);
-                       } else {
-                               languageSelector[0].setValue('none');
-                       }
+               var languageSelector = tab.down('combobox[itemId=language]');
+               if (!Ext.isEmpty(languageSelector) && !Ext.isBoolean(options)) {
+                       languageSelector.setValue(language ? language : 'none');
                }
                        // Update the term to use
-               tab.find('itemId', 'useTerm')[0].setValue(term);
+               if (!Ext.isBoolean(options)) {
+                       tab.down('component[itemId=useTerm]').setValue(term);
+               }
        },
        /*
         * This function builds the configuration object for the Abbreviation or Acronym to use fieldset
@@ -498,16 +546,16 @@ HTMLArea.Acronym = Ext.extend(HTMLArea.Plugin, {
         */
        okHandler: function (button, event) {
                this.restoreSelection();
-               var tab = this.dialog.findByType('tabpanel')[0].getActiveTab();
+               var tab = this.dialog.down('tabpanel').getActiveTab();
                var type = tab.getItemId();
-               var languageSelector = tab.find('itemId', 'language');
-               var language = !Ext.isEmpty(languageSelector) ? languageSelector[0].getValue() : '';
-               var term = tab.find('itemId', 'termSelector')[0].getValue();
+               var languageSelector = tab.down('component[itemId=language]');
+               var language = !Ext.isEmpty(languageSelector) ? languageSelector.getValue() : '';
+               var term = tab.down('component[itemId=termSelector]').getValue();
                if (!this.params.abbr) {
                        var abbr = this.editor.document.createElement(type);
-                       abbr.title = tab.find('itemId', 'useTerm')[0].getValue();
+                       abbr.title = tab.down('component[itemId=useTerm]').getValue();
                        if (term == abbr.title) {
-                               abbr.innerHTML = tab.find('itemId', 'abbrSelector')[0].getValue();
+                               abbr.innerHTML = tab.down('component[itemId=abbrSelector]').getValue();
                        } else {
                                abbr.innerHTML = this.params.text;
                        }
@@ -517,12 +565,12 @@ HTMLArea.Acronym = Ext.extend(HTMLArea.Plugin, {
                        this.editor.insertNodeAtSelection(abbr);
                } else {
                        var abbr = this.params.abbr;
-                       abbr.title = tab.find('itemId', 'useTerm')[0].getValue();
+                       abbr.title = tab.down('component[itemId=useTerm]').getValue();
                        if (language) {
                                this.getPluginInstance('Language').setLanguageAttributes(abbr, language);
                        }
                        if (term == abbr.title) {
-                               abbr.innerHTML = tab.find('itemId', 'abbrSelector')[0].getValue();
+                               abbr.innerHTML = tab.down('component[itemId=abbrSelector]').getValue();
                        }
                }
                this.close();
@@ -551,7 +599,7 @@ HTMLArea.Acronym = Ext.extend(HTMLArea.Plugin, {
                                button.setInactive(!(el.nodeName.toLowerCase() == 'acronym' && !this.pageTSConfiguration.noAcronym) && !(el.nodeName.toLowerCase() == 'abbr' && !this.pageTSConfiguration.noAbbr));
                        }
                        button.setTooltip({
-                               title: this.localize((button.disabled || button.inactive) ? 'Insert abbreviation' : 'Edit abbreviation')
+                               text: this.localize((button.disabled || button.inactive) ? 'Insert abbreviation' : 'Edit abbreviation')
                        });
                        button.contextMenuTitle = '';
                        if (this.dialog) {
index 38e0f40..b9b8780 100644 (file)
@@ -27,7 +27,8 @@
 /*
  * BlockElements Plugin for TYPO3 htmlArea RTE
  */
-HTMLArea.BlockElements = Ext.extend(HTMLArea.Plugin, {
+Ext.define('HTMLArea.BlockElements', {
+       extend: 'HTMLArea.Plugin',
        /*
         * This function gets called by the class constructor
         */
@@ -119,11 +120,12 @@ HTMLArea.BlockElements = Ext.extend(HTMLArea.Plugin, {
                };
                if (this.buttonsConfiguration.formatblock) {
                        dropDownConfiguration.width = this.buttonsConfiguration.formatblock.width ? parseInt(this.buttonsConfiguration.formatblock.width, 10) : 200;
+                       dropDownConfiguration.listConfig = {};
                        if (this.buttonsConfiguration.formatblock.listWidth) {
-                               dropDownConfiguration.listWidth = parseInt(this.buttonsConfiguration.formatblock.listWidth, 10);
+                               dropDownConfiguration.listConfig.width = parseInt(this.buttonsConfiguration.formatblock.listWidth, 10);
                        }
                        if (this.buttonsConfiguration.formatblock.maxHeight) {
-                               dropDownConfiguration.maxHeight = parseInt(this.buttonsConfiguration.formatblock.maxHeight, 10);
+                               dropDownConfiguration.listConfig.maxHeight = parseInt(this.buttonsConfiguration.formatblock.maxHeight, 10);
                        }
                }
                this.registerDropDown(dropDownConfiguration);
@@ -1205,16 +1207,16 @@ HTMLArea.BlockElements = Ext.extend(HTMLArea.Plugin, {
                        }
                }
                if (index == -1) {
-                       store.insert(0, new store.recordType({
+                       store.insert(0, {
                                text: this.localize('No block'),
                                value: 'none'
-                       }));
+                       });
                        select.setValue('none');
                } else {
-                       store.insert(0, new store.recordType({
+                       store.insert(0, {
                                text: this.localize('Remove block'),
                                value: 'none'
-                       }));
+                       });
                        select.setValue(store.getAt(index+1).get('value'));
                }
        },
index 5fa0d4b..3fc5d80 100644 (file)
 /*
  * Block Style Plugin for TYPO3 htmlArea RTE
  */
-HTMLArea.BlockStyle = Ext.extend(HTMLArea.Plugin, {
+/*
+ * Define data model for blockstyle selector box
+ */
+Ext.define('HTMLArea.model.BlockStyle', {
+       extend: 'Ext.data.Model',
+       fields: [{
+                       name: 'text',
+                       type: 'string'
+               },{
+                       name: 'value',
+                       type: 'string'
+               },{
+                       name: 'style',
+                       type: 'string'
+       }]
+});
+/*
+ * Define BlockStyle plugin
+ */
+Ext.define('HTMLArea.BlockStyle', {
+       extend: 'HTMLArea.Plugin',
        /*
         * This function gets called by the class constructor
         */
@@ -105,23 +125,28 @@ HTMLArea.BlockStyle = Ext.extend(HTMLArea.Plugin, {
                        fieldLabel = this.localize('Block style label');
                }
                var dropDownConfiguration = {
+                       action: 'onChange',
                        id: dropDownId,
                        tooltip: this.localize(dropDownId + '-Tooltip'),
                        fieldLabel: fieldLabel,
-                       options: [[this.localize('No style'), 'none']],
-                       action: 'onChange',
-                       storeFields: [ { name: 'text'}, { name: 'value'}, { name: 'style'} ],
-                       tpl: '<tpl for="."><div ext:qtip="{value}" style="{style}text-align:left;font-size:11px;" class="x-combo-list-item">{text}</div></tpl>'
+                       options: [{
+                               text: this.localize('No style'),
+                               value: 'none',
+                               style: ''
+                       }],
+                       model: 'HTMLArea.model.BlockStyle',
+                       template: '<div data-qtip="{value}" style="{style}" class="htmlarea-combo-list-item">{text}</div>'
                };
                if (this.pageTSconfiguration) {
                        if (this.pageTSconfiguration.width) {
                                dropDownConfiguration.width = parseInt(this.pageTSconfiguration.width, 10);
                        }
+                       dropDownConfiguration.listConfig = {};
                        if (this.pageTSconfiguration.listWidth) {
-                               dropDownConfiguration.listWidth = parseInt(this.pageTSconfiguration.listWidth, 10);
+                               dropDownConfiguration.listConfig.width = parseInt(this.pageTSconfiguration.listWidth, 10);
                        }
                        if (this.pageTSconfiguration.maxHeight) {
-                               dropDownConfiguration.maxHeight = parseInt(this.pageTSconfiguration.maxHeight, 10);
+                               dropDownConfiguration.listConfig.maxHeight = parseInt(this.pageTSconfiguration.maxHeight, 10);
                        }
                }
                this.registerDropDown(dropDownConfiguration);
@@ -209,7 +234,7 @@ HTMLArea.BlockStyle = Ext.extend(HTMLArea.Plugin, {
                        // Monitor editor changing mode
                this.editor.iframe.mon(this.editor, 'HTMLAreaEventModeChange', this.onModeChange, this);
                        // Create CSS Parser object
-               this.blockStyles = new HTMLArea.CSS.Parser({
+               this.blockStyles = Ext.create('HTMLArea.CSS.Parser', {
                        prefixLabelWithClassName: this.prefixLabelWithClassName,
                        postfixLabelWithClassName: this.postfixLabelWithClassName,
                        showTagFreeClasses: this.showTagFreeClasses,
@@ -284,10 +309,10 @@ HTMLArea.BlockStyle = Ext.extend(HTMLArea.Plugin, {
        initializeDropDown: function (dropDown) {
                var store = dropDown.getStore();
                store.removeAll(false);
-               store.insert(0, new store.recordType({
+               store.insert(0, {
                        text: this.localize('No style'),
                        value: 'none'
-               }));
+               });
                dropDown.setValue('none');
        },
        /*
@@ -313,11 +338,11 @@ HTMLArea.BlockStyle = Ext.extend(HTMLArea.Plugin, {
                                                style = HTMLArea.classesValues[RegExp.leftContext + '-'];
                                        }
                                }
-                               store.add(new store.recordType({
+                               store.add({
                                        text: value,
                                        value: cssClass,
                                        style: style
-                               }));
+                               });
                        }, this);
                }
        },
@@ -336,10 +361,10 @@ HTMLArea.BlockStyle = Ext.extend(HTMLArea.Plugin, {
                                }
                        }
                        if (index == -1 && !noUnknown) {
-                               store.add(new store.recordType({
+                               store.add({
                                        text: this.localize('Unknown style'),
                                        value: classNames[classNames.length-1]
-                               }));
+                               });
                                index = store.getCount()-1;
                                dropDown.setValue(classNames[classNames.length-1]);
                                if (!defaultClass) {
index 3abf811..2f15cec 100644 (file)
@@ -31,7 +31,8 @@
 /*
  * Character Map Plugin for TYPO3 htmlArea RTE
  */
-HTMLArea.CharacterMap = Ext.extend(HTMLArea.Plugin, {
+Ext.define('HTMLArea.CharacterMap', {
+       extend: 'HTMLArea.Plugin',
        /*
         * This function gets called by the class constructor
         */
@@ -50,17 +51,24 @@ HTMLArea.CharacterMap = Ext.extend(HTMLArea.Plugin, {
                };
                this.registerPluginInformation(pluginInformation);
                /*
-                * Registering the button
+                * Registering the buttons
+                */
+               for (var i = 0, n = this.buttons.length; i < n; ++i) {
+                       var button = this.buttons[i];
+                       buttonId = button[0];
+                       var buttonConfiguration = {
+                               id: buttonId,
+                               tooltip: this.localize(buttonId + '-Tooltip'),
+                               action: 'onButtonPress',
+                               context: button[1],
+                               dialog: false,
+                               iconCls: 'htmlarea-action-' + button[2]
+                       };
+                       this.registerButton(buttonConfiguration);
+               }
+               /*
+                * Localizing the maps
                 */
-               var buttonId = 'InsertCharacter';
-               var buttonConfiguration = {
-                       id              : buttonId,
-                       tooltip         : this.localize(buttonId + '-Tooltip'),
-                       action          : 'onButtonPress',
-                       dialog          : true,
-                       iconCls         : 'htmlarea-action-character-insert-from-map'
-               };
-               this.registerButton(buttonConfiguration);
                Ext.iterate(this.maps, function (key, map, maps) {
                        for (var i = map.length; --i >= 0;) {
                                maps[key][i].push(this.localize(map[i][1]));
@@ -69,6 +77,13 @@ HTMLArea.CharacterMap = Ext.extend(HTMLArea.Plugin, {
                return true;
         },
        /*
+        * The list of buttons added by this plugin
+        */
+       buttons: [
+               ['InsertCharacter', null, 'character-insert-from-map'],
+               ['InsertSoftHyphen', null, 'soft-hyphen-insert']
+       ],
+       /*
         * Character maps
         */
        maps: {
@@ -334,12 +349,25 @@ HTMLArea.CharacterMap = Ext.extend(HTMLArea.Plugin, {
                        // Could be a button or its hotkey
                var buttonId = this.translateHotKey(id);
                buttonId = buttonId ? buttonId : id;
-               this.openDialogue(
-                       buttonId,
-                       'Insert special character',
-                       this.getWindowDimensions({width:434, height:360}, buttonId),
-                       this.buildTabItems()
-               );
+               switch (buttonId) {
+                       case 'InsertCharacter':
+                               this.openDialogue(
+                                       buttonId,
+                                       'Insert special character',
+                                       this.getWindowDimensions(
+                                               {
+                                                       width: 402,
+                                                       height: 360
+                                               },
+                                               buttonId
+                                       ),
+                                       this.buildTabItems()
+                               );
+                               break;
+                       case 'InsertSoftHyphen':
+                               this.insertEntity('\xAD');
+                               break;
+               }
                return false;
        },
        /*
@@ -354,14 +382,13 @@ HTMLArea.CharacterMap = Ext.extend(HTMLArea.Plugin, {
         * @return      void
         */
        openDialogue: function (buttonId, title, dimensions, tabItems, handler) {
-               this.dialog = new Ext.Window({
+               this.dialog = Ext.create('Ext.window.Window', {
                        title: this.localize(title),
                        cls: 'htmlarea-window',
                        border: false,
                        width: dimensions.width,
-                       height: 'auto',
-                               // As of ExtJS 3.1, JS error with IE when the window is resizable
-                       resizable: !Ext.isIE,
+                       layout: 'anchor',
+                       resizable: true,
                        iconCls: this.getButton(buttonId).iconCls,
                        listeners: {
                                close: {
@@ -376,10 +403,6 @@ HTMLArea.CharacterMap = Ext.extend(HTMLArea.Plugin, {
                                        activate: {
                                                fn: this.resetFocus,
                                                scope: this
-                                       },
-                                       tabchange: {
-                                               fn: this.syncHeight,
-                                               scope: this
                                        }
                                },
                                items: tabItems
@@ -399,12 +422,12 @@ HTMLArea.CharacterMap = Ext.extend(HTMLArea.Plugin, {
                var tabItems = [];
                Ext.iterate(this.maps, function (id, map) {
                        tabItems.push({
-                               xtype: 'box',
-                               cls: 'character-map',
+                               xtype: 'component',
+                               cls: 'htmlarea-character-map',
                                title: this.localize(id),
                                itemId: id,
-                               tpl: new Ext.XTemplate(
-                                       '<tpl for="."><a href="#" class="character" hidefocus="on" ext:qtitle="<span>&</span>{1};" ext:qtip="{2}">{0}</a></tpl>'
+                               tpl: Ext.create('Ext.XTemplate',
+                                       '<tpl for="."><a href="#" class="htmlarea-character-map-character" hidefocus="on" data-qtitle="<span>&</span>{1};" data-qtip="{2}">{0}</a></tpl>'
                                ),
                                listeners: {
                                        render: {
@@ -428,26 +451,43 @@ HTMLArea.CharacterMap = Ext.extend(HTMLArea.Plugin, {
                component.mon(component.el, 'click', this.insertCharacter, this, {delegate: 'a'});
        },
        /*
-        * Insert the selected entity
+        * Handle the click on an item of the map
         *
         * @param       object          event: the Ext event
         * @param       HTMLelement     target: the html element target
         *
-        * @return      void
+        * @return      boolean
         */
        insertCharacter: function (event, target) {
                event.stopEvent();
                this.editor.focus();
                this.restoreSelection();
                var entity = Ext.get(target).dom.innerHTML;
+               this.insertEntity(entity);
                if (Ext.isIE) {
-                       this.editor.insertHTML(entity);
                        this.saveSelection();
+               }
+               return false;
+       },
+       /*
+        * Insert the selected entity
+        *
+        * @param       string          entity: the entity to insert at the current selection
+        *
+        * @return      void
+        */
+       insertEntity: function (entity) {
+               this.editor.focus();
+               if (Ext.isIE) {
+                       this.editor.insertHTML(entity);
                } else {
                                // Firefox and WebKit convert '&nbsp;' to '&amp;nbsp;'
-                       this.editor.insertNodeAtSelection(this.editor.document.createTextNode(((Ext.isGecko || Ext.isWebKit) && entity == '&nbsp;') ? '\xA0' : entity));
+                       var node = this.editor.document.createTextNode(((Ext.isGecko || Ext.isWebKit) && entity == '&nbsp;') ? '\xA0' : entity);
+                       this.editor.insertNodeAtSelection(node);
+                       if (!Ext.isIE) {
+                               this.editor.selectNode(node, false);
+                       }
                }
-               return false;
        },
        /*
         * Reset focus on the the current selection, if at all possible
index aca7694..13bcbce 100644 (file)
@@ -9,6 +9,9 @@
                        <trans-unit id="InsertCharacter-Tooltip" xml:space="preserve">
                                <source>Insert special character</source>
                        </trans-unit>
+                       <trans-unit id="InsertSoftHyphen-Tooltip" xml:space="preserve">
+                               <source>Insert soft hyphen</source>
+                       </trans-unit>
                        <trans-unit id="Insert special character" xml:space="preserve">
                                <source>Insert special character</source>
                        </trans-unit>
index 6dfab8f..1cad4ad 100644 (file)
@@ -30,7 +30,8 @@
 /*
  * Context Menu Plugin for TYPO3 htmlArea RTE
  */
-HTMLArea.ContextMenu = Ext.extend(HTMLArea.Plugin, {
+Ext.define('HTMLArea.ContextMenu', {
+       extend: 'HTMLArea.Plugin',
        /*
         * This function gets called by the class constructor
         */
@@ -49,7 +50,7 @@ HTMLArea.ContextMenu = Ext.extend(HTMLArea.Plugin, {
                 * Registering plugin "About" information
                 */
                var pluginInformation = {
-                       version         : '3.2',
+                       version         : '4.0',
                        developer       : 'Mihai Bazon & Stanislas Rolland',
                        developerUrl    : 'http://www.sjbr.ca/',
                        copyrightOwner  : 'dynarch.com & Stanislas Rolland',
@@ -64,30 +65,51 @@ HTMLArea.ContextMenu = Ext.extend(HTMLArea.Plugin, {
         * This function gets called when the editor gets generated
         */
        onGenerate: function() {
-                       // Build the context menu
-               this.menu = new Ext.menu.Menu(Ext.applyIf({
-                       cls: 'htmlarea-context-menu',
-                       defaultType: 'menuitem',
-                       listeners: {
-                               itemClick: {
-                                       fn: this.onItemClick,
-                                       scope: this
-                               },
-                               show: {
-                                       fn: this.onShow,
-                                       scope: this
-                               },
-                               hide: {
-                                       fn: this.onHide,
-                                       scope: this
-                               }
-                       },
-                       items: this.buildItemsConfig()
-               }, this.pageTSConfiguration));
                        // Monitor contextmenu clicks on the iframe
-               this.menu.mon(Ext.get(this.editor.document.documentElement), 'contextmenu', this.show, this);
+               this.editor.iframe.mon(Ext.get(this.editor.document.documentElement), 'contextmenu', this.show, this, {stopEvent: true, single: true});
+       },
+       /*
+        * Handler to show the context menu
+        */
+       show: function (event, target) {
+                       // Build the context menu on first use
+               if (!this.menu) {
+                       this.menu = Ext.create(Ext.menu.Menu, Ext.apply({
+                               bodyCls: 'htmlarea-context-menu',
+                               defaultType: 'menuitem',
+                               floating: true,
+                               items: this.buildItemsConfig(),
+                               listeners: {
+                                       afterrender: {
+                                               fn: this.afterRenderMenu,
+                                               scope: this,
+                                               single: true
+                                       },
+                                       click: {
+                                               fn: this.onItemClick,
+                                               scope: this
+                                       },
+                                       hide: {
+                                               fn: this.onMenuHide,
+                                               scope: this
+                                       },
+                                       show: {
+                                               fn: this.onMenuShow,
+                                               scope: this
+                                       }
+                               },
+                               maxHeight: 500
+                       }, this.pageTSConfiguration));
+               }
+                       // Need to wait a while for the toolbar state to be updated
+               Ext.Function.defer(this.showMenu, 150, this, [target]);
+       },
+       /*
+        * Handler afterrender
+        */
+       afterRenderMenu: function (menu) {
                        // Monitor editor being destroyed
-               this.menu.mon(this.editor, 'beforedestroy', this.onBeforeDestroy, this, {single: true});
+               menu.mon(this.editor.iframe, 'beforedestroy', this.onBeforeDestroy, this, {single: true});
        },
        /*
         * Create the menu items config
@@ -101,10 +123,10 @@ HTMLArea.ContextMenu = Ext.extend(HTMLArea.Plugin, {
                        firstInGroup = true;
                        Ext.each(row, function (group) {
                                if (!firstInGroup) {
-                                       // If a visible item was added to the line
+                                               // If a visible item was added to the line
                                        itemsConfig.push({
                                                        xtype: 'menuseparator',
-                                                       cls: 'separator'
+                                                       cls: 'htmlarea-context-menu-separator'
                                        });
                                }
                                firstInGroup = true;
@@ -118,12 +140,23 @@ HTMLArea.ContextMenu = Ext.extend(HTMLArea.Plugin, {
                                                        var itemId = button.getItemId();
                                                        itemsConfig.push({
                                                                itemId: itemId,
-                                                               cls: 'button',
-                                                               overCls: 'hover',
-                                                               text: (button.contextMenuTitle ? button.contextMenuTitle : button.tooltip.title),
+                                                               cls: 'htmlarea-context-menu-item',
+                                                               overCls: 'htmlarea-context-menu-hover',
+                                                               text: (button.contextMenuTitle ? button.contextMenuTitle : button.tooltip.text),
                                                                iconCls: button.iconCls,
                                                                helpText: (button.helpText ? button.helpText : this.localize(itemId + '-tooltip')),
-                                                               hidden: true
+                                                               listeners: {
+                                                                       afterrender: {
+                                                                               fn: function (menuitem) {
+                                                                                       if (menuitem.helpText) {
+                                                                                               Ext.tip.QuickTipManager.register({
+                                                                                                       target: menuitem,
+                                                                                                       text: menuitem.helpText
+                                                                                               });
+                                                                                       }
+                                                                               }
+                                                                       }
+                                                               }
                                                        });
                                                        firstInGroup = false;
                                                }
@@ -138,7 +171,7 @@ HTMLArea.ContextMenu = Ext.extend(HTMLArea.Plugin, {
                if (!firstInGroup) {
                        itemsConfig.push({
                                        xtype: 'menuseparator',
-                                       cls: 'separator'
+                                       cls: 'htmlarea-context-menu-separator'
                        });
                }
                        // Add special target delete item
@@ -153,24 +186,10 @@ HTMLArea.ContextMenu = Ext.extend(HTMLArea.Plugin, {
                return itemsConfig;
        },
        /*
-        * Handler when the menu gets shown
-        */
-       onShow: function () {
-               this.menu.mon(Ext.get(this.editor.document.documentElement), 'mousedown', this.menu.hide, this.menu, {single: true});
-       },
-       /*
-        * Handler when the menu gets hidden
+        * Handler when the mouse goes down in the editor iframe
         */
-       onHide: function () {
-               this.menu.mun(Ext.get(this.editor.document.documentElement), 'mousedown', this.menu.hide, this.menu);
-       },
-       /*
-        * Handler to show the context menu
-        */
-       show: function (event, target) {
-               event.stopEvent();
-                       // Need to wait a while for the toolbar state to be updated
-               this.showMenu.defer(150, this, [target]);
+       hideMenu: function () {
+               this.menu.hide();
        },
        /*
         * Show the context menu
@@ -180,48 +199,54 @@ HTMLArea.ContextMenu = Ext.extend(HTMLArea.Plugin, {
                if (!Ext.isIE) {
                        this.ranges = this.editor.getSelectionRanges();
                }
-               var iframeEl = this.editor.iframe.getEl();
-                       // Show the context menu
-               this.menu.showAt([Ext.fly(target).getX() + iframeEl.getX(), Ext.fly(target).getY() + iframeEl.getY()]);
+                       // There is nothing to understand here...
+               this.menu.showBy(this.editor.iframe, 'tl-tr?');
+               this.menu.showBy(this.editor.iframe, 'tl-tr?');
        },
        /*
         * Show items depending on context
         */
        showContextItems: function (target) {
-               var lastIsSeparator = false, lastIsButton = false, xtype, lastVisible;
-               this.menu.cascade(function (menuItem) {
+               var lastIsSeparator = false,
+                       lastIsButton = false,
+                       xtype,
+                       lastVisible;
+               this.menu.items.each(function (menuItem) {
                        xtype = menuItem.getXType();
-                       if (xtype === 'menuseparator') {
-                               menuItem.setVisible(lastIsButton);
-                               lastIsButton = false;
-                       } else if (xtype === 'menuitem') {
-                               var button = this.getButton(menuItem.getItemId());
-                               if (button) {
-                                       var text = button.contextMenuTitle ? button.contextMenuTitle : button.tooltip.title;
-                                       if (menuItem.text != text) {
-                                               menuItem.setText(text);
-                                       }
-                                       menuItem.helpText = button.helpText ? button.helpText : menuItem.helpText;
-                                       menuItem.setVisible(!button.disabled);
-                                       lastIsButton = lastIsButton || !button.disabled;
-                               } else {
-                                               // Special target delete item
-                                       this.deleteTarget = target;
-                                       if (/^(html|body)$/i.test(target.nodeName)) {
-                                               this.deleteTarget = null;
-                                       } else if (/^(table|thead|tbody|tr|td|th|tfoot)$/i.test(target.nodeName)) {
-                                               this.deleteTarget = Ext.fly(target).findParent('table');
-                                       } else if (/^(ul|ol|dl|li|dd|dt)$/i.test(target.nodeName)) {
-                                               this.deleteTarget = Ext.fly(target).findParent('ul') || Ext.fly(target).findParent('ol') || Ext.fly(target).findParent('dl');
-                                       }
-                                       if (this.deleteTarget) {
-                                               menuItem.setVisible(true);
-                                               menuItem.setText(this.localize('Remove the') + ' &lt;' + this.deleteTarget.nodeName.toLowerCase() + '&gt; ');
-                                               lastIsButton = true;
+                       switch (xtype) {
+                               case 'menuseparator':
+                                       menuItem.setVisible(lastIsButton);
+                                       lastIsButton = false;
+                                       break;
+                               case 'menuitem':
+                                       var button = this.getButton(menuItem.getItemId());
+                                       if (button) {
+                                               var text = button.contextMenuTitle ? button.contextMenuTitle : button.tooltip.text;
+                                               if (menuItem.text != text) {
+                                                       menuItem.setText(text);
+                                               }
+                                               menuItem.helpText = button.helpText ? button.helpText : menuItem.helpText;
+                                               menuItem.setVisible(!button.disabled);
+                                               lastIsButton = lastIsButton || !button.disabled;
                                        } else {
-                                               menuItem.setVisible(false);
+                                                       // Special target delete item
+                                               this.deleteTarget = target;
+                                               if (/^(html|body)$/i.test(target.nodeName)) {
+                                                       this.deleteTarget = null;
+                                               } else if (/^(table|thead|tbody|tr|td|th|tfoot)$/i.test(target.nodeName)) {
+                                                       this.deleteTarget = Ext.fly(target).findParent('table');
+                                               } else if (/^(ul|ol|dl|li|dd|dt)$/i.test(target.nodeName)) {
+                                                       this.deleteTarget = Ext.fly(target).findParent('ul') || Ext.fly(target).findParent('ol') || Ext.fly(target).findParent('dl');
+                                               }
+                                               if (this.deleteTarget) {
+                                                       menuItem.setVisible(true);
+                                                       menuItem.setText(this.localize('Remove the') + ' &lt;' + this.deleteTarget.nodeName.toLowerCase() + '&gt; ');
+                                                       lastIsButton = true;
+                                               } else {
+                                                       menuItem.setVisible(false);
+                                               }
                                        }
-                               }
+                                       break;
                        }
                        if (!menuItem.hidden) {
                                lastVisible = menuItem;
@@ -233,43 +258,61 @@ HTMLArea.ContextMenu = Ext.extend(HTMLArea.Plugin, {
                }
        },
        /*
-        * Handler invoked when a menu item is clicked on
+        * Handler invoked when a menu is clicked on
         */
-       onItemClick: function (item, event) {
-               if (!Ext.isIE) {
-                       this.editor.setSelectionRanges(this.ranges);
-               }
-               var button = this.getButton(item.getItemId());
-               if (button) {
-                       button.fireEvent('HTMLAreaEventContextMenu', button, event);
-               } else if (item.getItemId() === 'DeleteTarget') {
-                               // Do not leave a non-ie table cell empty
-                       var parent = this.deleteTarget.parentNode;
-                       parent.normalize();
-                       if (!Ext.isIE && /^(td|th)$/i.test(parent.nodeName) && parent.childNodes.length == 1) {
-                                       // Do not leave a non-ie table cell empty
-                               parent.appendChild(this.editor.document.createElement('br'));
+       onItemClick: function (menu, item, event) {
+               if (item) {
+                       if (!Ext.isIE) {
+                               this.editor.setSelectionRanges(this.ranges);
                        }
-                               // Try to find a reasonable replacement selection
-                       var nextSibling = this.deleteTarget.nextSibling;
-                       var previousSibling = this.deleteTarget.previousSibling;
-                       if (nextSibling) {
-                               this.editor.selectNode(nextSibling, true);
-                       } else if (previousSibling) {
-                               this.editor.selectNode(previousSibling, false);
+                       var button = this.getButton(item.getItemId());
+                       if (button) {
+                               button.fireEvent('HTMLAreaEventContextMenu', button, event, null);
+                       } else if (item.getItemId() === 'DeleteTarget') {
+                                       // Do not leave a non-ie table cell empty
+                               var parent = this.deleteTarget.parentNode;
+                               parent.normalize();
+                               if (!Ext.isIE && /^(td|th)$/i.test(parent.nodeName) && parent.childNodes.length == 1) {
+                                               // Do not leave a non-ie table cell empty
+                                       parent.appendChild(this.editor.document.createElement('br'));
+                               }
+                                       // Try to find a reasonable replacement selection
+                               var nextSibling = this.deleteTarget.nextSibling;
+                               var previousSibling = this.deleteTarget.previousSibling;
+                               if (nextSibling) {
+                                       this.editor.selectNode(nextSibling, true);
+                               } else if (previousSibling) {
+                                       this.editor.selectNode(previousSibling, false);
+                               }
+                               HTMLArea.removeFromParent(this.deleteTarget);
+                               this.editor.updateToolbar();
                        }
-                       HTMLArea.removeFromParent(this.deleteTarget);
-                       this.editor.updateToolbar();
                }
        },
        /*
+        * Handler when the menu gets hidden
+        */
+       onMenuHide: function (menu) {
+                       // Stop listening to mousedown
+               menu.mun(Ext.get(this.editor.document.documentElement), 'mousedown', this.hideMenu, this);
+                       // Resume listening to contextmenu
+               menu.mon(Ext.get(this.editor.document.documentElement), 'contextmenu', this.show, this, {stopEvent: true, single: true});
+       },
+       /*
+        * Handler when the menu gets shown
+        */
+       onMenuShow: function (menu) {
+                       // Hide the menu when the mouse goes down in the editor iframe
+               menu.mon(Ext.get(this.editor.document.documentElement), 'mousedown', this.hideMenu, this, { single: true });
+       },
+       /*
         * Handler invoked when the editor is about to be destroyed
         */
        onBeforeDestroy: function () {
                this.menu.items.each(function (menuItem) {
                        Ext.QuickTips.unregister(menuItem);
                });
-               this.menu.removeAll(true);
-               this.menu.destroy();
+               this.menu.removeAll(true);
+               this.menu.destroy();
        }
 });
index 58690c9..e3078e3 100644 (file)
@@ -27,7 +27,8 @@
 /*
  * Copy Paste for TYPO3 htmlArea RTE
  */
-HTMLArea.CopyPaste = Ext.extend(HTMLArea.Plugin, {
+Ext.define('HTMLArea.CopyPaste', {
+       extend: 'HTMLArea.Plugin',
        /*
         * This function gets called by the class constructor
         */
@@ -144,7 +145,7 @@ HTMLArea.CopyPaste = Ext.extend(HTMLArea.Plugin, {
                                        if (Ext.isOpera || Ext.isGecko2) {
                                                var cleaner = this.getButton('CleanWord');
                                                if (cleaner) {
-                                                       cleaner.fireEvent.defer(250, cleaner, ['click', cleaner]);
+                                                       Ext.Function.defer(cleaner.fireEvent, 250, cleaner, ['click', cleaner]);
                                                }
                                        }
                                        break;
@@ -162,7 +163,7 @@ HTMLArea.CopyPaste = Ext.extend(HTMLArea.Plugin, {
                                this.editor.inhibitKeyboardInput = true;
                                var bookmark = this.editor.getBookmark(this.editor._createRange(this.editor._getSelection()));
                                var html = this.editor.getInnerHTML();
-                               this.revertPaste.defer(200, this, [html, bookmark]);
+                               Ext.Function.defer(this.revertPaste, 200, this, [html, bookmark]);
                        }
                        return false;
                }
@@ -202,7 +203,7 @@ HTMLArea.CopyPaste = Ext.extend(HTMLArea.Plugin, {
         * This function removes any link left over by the cut operation
         */
        cutHandler: function (event) {
-               this.removeEmptyLink.defer(50, this);
+               Ext.Function.defer(this.removeEmptyLink, 50, this);
        },
        /*
         * This function unlinks any empty link left over by the cut operation
index b2d22b5..467a3ef 100644 (file)
@@ -26,7 +26,8 @@
 /**
  * Default Clean Plugin for TYPO3 htmlArea RTE
  */
-HTMLArea.DefaultClean = Ext.extend(HTMLArea.Plugin, {
+Ext.define('HTMLArea.DefaultClean', {
+       extend: 'HTMLArea.Plugin',
        /*
         * This function gets called by the class constructor
         */
@@ -166,6 +167,6 @@ HTMLArea.DefaultClean = Ext.extend(HTMLArea.Plugin, {
         * Handler for paste, dragdrop and drop events
         */
        wordCleanHandler: function (event) {
-               this.clean.defer(250, this);
+               Ext.Function.defer(this.clean, 250, this);
        }
 });
index b281c91..584830e 100644 (file)
@@ -29,7 +29,8 @@
 /*
  * Image Plugin for TYPO3 htmlArea RTE
  */
-HTMLArea.DefaultImage = Ext.extend(HTMLArea.Plugin, {
+Ext.define('HTMLArea.DefaultImage', {
+       extend: 'HTMLArea.Plugin',
        /*
         * This function gets called by the class constructor
         */
@@ -63,7 +64,7 @@ HTMLArea.DefaultImage = Ext.extend(HTMLArea.Plugin, {
                 * Registering plugin "About" information
                 */
                var pluginInformation = {
-                       version         : '2.2',
+                       version         : '3.0',
                        developer       : 'Stanislas Rolland',
                        developerUrl    : 'http://www.sjbr.ca/',
                        copyrightOwner  : 'Stanislas Rolland',
@@ -91,17 +92,24 @@ HTMLArea.DefaultImage = Ext.extend(HTMLArea.Plugin, {
         * Sets of default configuration values for dialogue form fields
         */
        configDefaults: {
-               combo: {
+               combobox: {
+                       cls: 'htmlarea-combo',
+                       displayField: 'text',
+                       listConfig: {
+                               cls: 'htmlarea-combo-list',
+                               getInnerTpl: function () {
+                                       return '<div data-qtip="{value}" class="htmlarea-combo-list-item">{text}</div>';
+                               }
+                       },
                        editable: true,
+                       forceSelection: true,
+                       helpIcon: true,
+                       queryMode: 'local',
                        selectOnFocus: true,
-                       typeAhead: true,
                        triggerAction: 'all',
-                       forceSelection: true,
-                       mode: 'local',
+                       typeAhead: true,
                        valueField: 'value',
-                       displayField: 'text',
-                       helpIcon: true,
-                       tpl: '<tpl for="."><div ext:qtip="{value}" style="text-align:left;font-size:11px;" class="x-combo-list-item">{text}</div></tpl>'
+                       xtype: 'combobox'
                }
        },
        /*
@@ -151,11 +159,11 @@ HTMLArea.DefaultImage = Ext.extend(HTMLArea.Plugin, {
                        // Open dialogue window
                this.openDialogue(
                        buttonId,
-                       this.getButton(buttonId).tooltip.title,
+                       this.getButton(buttonId).tooltip.text,
                        this.getWindowDimensions(
                                {
                                        width: 460,
-                                       height:300
+                                       height: 300
                                },
                                buttonId
                        ),
@@ -174,14 +182,13 @@ HTMLArea.DefaultImage = Ext.extend(HTMLArea.Plugin, {
         * @return      void
         */
        openDialogue: function (buttonId, title, dimensions, tabItems) {
-               this.dialog = new Ext.Window({
+               this.dialog = Ext.create('Ext.window.Window', {
                        title: this.localize(title) || title,
                        cls: 'htmlarea-window',
                        border: false,
                        width: dimensions.width,
-                       height: 'auto',
-                               // As of ExtJS 3.1, JS error with IE when the window is resizable
-                       resizable: !Ext.isIE,
+                       layout: 'anchor',
+                       resizable: true,
                        iconCls: this.getButton(buttonId).iconCls,
                        listeners: {
                                close: {
@@ -195,17 +202,11 @@ HTMLArea.DefaultImage = Ext.extend(HTMLArea.Plugin, {
                                activeTab: 0,
                                defaults: {
                                        xtype: 'container',
-                                       layout: 'form',
+                                       layout: 'anchor',
                                        defaults: {
                                                labelWidth: 100
                                        }
                                },
-                               listeners: {
-                                       tabchange: {
-                                               fn: this.syncHeight,
-                                               scope: this
-                                       }
-                               },
                                items: tabItems
                        },
                        buttons: [
@@ -234,10 +235,10 @@ HTMLArea.DefaultImage = Ext.extend(HTMLArea.Plugin, {
                                                labelSeparator: ''
                                        },
                                        items: [{
-                                                       itemId: 'url',
                                                        fieldLabel: this.localize('Image URL:'),
-                                                       value: this.parameters.url,
-                                                       helpTitle: this.localize('Enter the image URL here')
+                                                       helpTitle: this.localize('Enter the image URL here'),
+                                                       itemId: 'url',
+                                                       value: this.parameters.url
                                                },{
                                                        itemId: 'alt',
                                                        fieldLabel: this.localize('Alternate text:'),
@@ -280,6 +281,52 @@ HTMLArea.DefaultImage = Ext.extend(HTMLArea.Plugin, {
                });
                        // Layout tab
                if (!this.removeItems.test('layout')) {
+                               // Create image align options global store
+                       var imageAlignStore = Ext.data.StoreManager.lookup('HTMLArea' + '-store-' + this.name + 'imageAlign');
+                       if (!imageAlignStore) {
+                               imageAlignStore = Ext.create('Ext.data.ArrayStore', {
+                                       model: 'HTMLArea.model.Default',
+                                       storeId: 'HTMLArea' + '-store-' + this.name + 'imageAlign'
+                               });
+                               imageAlignStore.loadData([
+                                       {
+                                               text: this.localize('Not set'),
+                                               value: ''
+                                       },{
+                                               text: this.localize('Bottom'),
+                                               value: 'bottom'
+                                       },{
+                                               text: this.localize('Middle'),
+                                               value: 'middle'
+                                       },{
+                                               text: this.localize('Top'),
+                                               value: 'top'
+                                       }
+                               ]);
+                       }
+                               // Create cssFloat options global store
+                       var cssFloatStore = Ext.data.StoreManager.lookup('HTMLArea' + '-store-' + this.name + 'cssFloat');
+                       if (!cssFloatStore) {
+                               cssFloatStore = Ext.create('Ext.data.ArrayStore', {
+                                       model: 'HTMLArea.model.Default',
+                                       storeId: 'HTMLArea' + '-store-' + this.name + 'cssFloat'
+                               });
+                               cssFloatStore.loadData([
+                                       {
+                                               text: this.localize('Not set'),
+                                               value: ''
+                                       },{
+                                               text: this.localize('Non-floating'),
+                                               value: 'none'
+                                       },{
+                                               text: this.localize('Left'),
+                                               value: 'left'
+                                       },{
+                                               text: this.localize('Right'),
+                                               value: 'right'
+                                       }
+                               ]);
+                       }
                        tabItems.push({
                                title: this.localize('Layout'),
                                items: [{
@@ -287,57 +334,43 @@ HTMLArea.DefaultImage = Ext.extend(HTMLArea.Plugin, {
                                                defaultType: 'textfield',
                                                defaults: {
                                                        helpIcon: true,
-                                                       width: 250,
+                                                       width: 300,
                                                        labelSeparator: ''
                                                },
                                                items: [
-                                                       Ext.apply({
-                                                               xtype: 'combo',
-                                                               fieldLabel: this.localize('Image alignment:'),
-                                                               itemId: 'align',
-                                                               value: this.parameters.align,
-                                                               helpTitle: this.localize('Positioning of this image'),
-                                                               store: new Ext.data.ArrayStore({
-                                                                       autoDestroy:  true,
-                                                                       fields: [ { name: 'text'}, { name: 'value'}],
-                                                                       data: [
-                                                                               [this.localize('Not set'), ''],
-                                                                               [this.localize('Bottom'), 'bottom'],
-                                                                               [this.localize('Middle'), 'middle'],
-                                                                               [this.localize('Top'), 'top']
-                                                                       ]
-                                                               }),
-                                                               hidden: this.removeItems.test('align'),
-                                                               hideLabel: this.removeItems.test('align')
-                                                               }, this.configDefaults['combo'])
-                                                       ,{
-                                                               itemId: 'border',
+                                                       Ext.applyIf(
+                                                               {
+                                                                       fieldLabel: this.localize('Image alignment:'),
+                                                                       helpTitle: this.localize('Positioning of this image'),
+                                                                       hidden: this.removeItems.test('align'),
+                                                                       hideLabel: this.removeItems.test('align'),
+                                                                       itemId: 'align',
+                                                                       store: imageAlignStore,
+                                                                       value: this.parameters.align
+                                                               },
+                                                               this.configDefaults['combobox']
+                                                       ),
+                                                       {
                                                                fieldLabel: this.localize('Border thickness:'),
-                                                               width: 100,
-                                                               value: this.parameters.border,
                                                                helpTitle: this.localize('Leave empty for no border'),
                                                                hidden: this.removeItems.test('border'),
-                                                               hideLabel: this.removeItems.test('border')
+                                                               hideLabel: this.removeItems.test('border'),
+                                                               itemId: 'border',
+                                                               value: this.parameters.border,
+                                                               width: 200
                                                        },
-                                                       Ext.apply({
-                                                               xtype: 'combo',
-                                                               fieldLabel: this.localize('Float:'),
-                                                               itemId: 'cssFloat',
-                                                               value: this.parameters.cssFloat,
-                                                               helpTitle: this.localize('Where the image should float'),
-                                                               store: new Ext.data.ArrayStore({
-                                                                       autoDestroy:  true,
-                                                                       fields: [ { name: 'text'}, { name: 'value'}],
-                                                                       data: [
-                                                                               [this.localize('Not set'), ''],
-                                                                               [this.localize('Non-floating'), 'none'],
-                                                                               [this.localize('Left'), 'left'],
-                                                                               [this.localize('Right'), 'right']
-                                                                       ]
-                                                               }),
-                                                               hidden: this.removeItems.test('float'),
-                                                               hideLabel: this.removeItems.test('float')
-                                                               }, this.configDefaults['combo'])
+                                                       Ext.applyIf(
+                                                               {
+                                                                       fieldLabel: this.localize('Float:'),
+                                                                       helpTitle: this.localize('Where the image should float'),
+                                                                       hidden: this.removeItems.test('float'),
+                                                                       hideLabel: this.removeItems.test('float'),
+                                                                       itemId: 'cssFloat',
+                                                                       store: cssFloatStore,
+                                                                       value: this.parameters.cssFloat
+                                                               },
+                                                               this.configDefaults['combobox']
+                                                       )
                                                ]
                                }]
                        });
@@ -351,7 +384,7 @@ HTMLArea.DefaultImage = Ext.extend(HTMLArea.Plugin, {
                                                defaultType: 'textfield',
                                                defaults: {
                                                        helpIcon: true,
-                                                       width: 100,
+                                                       width: 200,
                                                        labelSeparator: ''
                                                },
                                                items: [{
@@ -393,8 +426,8 @@ HTMLArea.DefaultImage = Ext.extend(HTMLArea.Plugin, {
         * Handler invoked when the Preview button is clicked
         */
        onPreviewClick: function () {
-               var tabPanel = this.dialog.find('itemId', 'tabpanel')[0];
-               var urlField = this.dialog.find('itemId', 'url')[0];
+               var tabPanel = this.dialog.down('component[itemId=tabpanel]');
+               var urlField = this.dialog.down('component[itemId=url]');
                var url = urlField.getValue().trim();
                if (url) {
                        try {
@@ -419,12 +452,12 @@ HTMLArea.DefaultImage = Ext.extend(HTMLArea.Plugin, {
         * Handler invoked when the OK button is clicked
         */
        onOK: function () {
-               var urlField = this.dialog.find('itemId', 'url')[0];
+               var urlField = this.dialog.down('component[itemId=url]');
                var url = urlField.getValue().trim();
                if (url) {
                        var fieldNames = ['url', 'alt', 'align', 'border', 'paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft', 'cssFloat'];
                        Ext.each(fieldNames, function (fieldName) {
-                               var field = this.dialog.find('itemId', fieldName)[0];
+                               var field = this.dialog.down('component[itemId=' + fieldName + ']');
                                if (field && !field.hidden) {
                                        this.parameters[fieldName] = field.getValue();
                                }
@@ -432,7 +465,7 @@ HTMLArea.DefaultImage = Ext.extend(HTMLArea.Plugin, {
                        this.insertImage();
                        this.close();
                } else {
-                       var tabPanel = this.dialog.find('itemId', 'tabpanel')[0];
+                       var tabPanel = this.dialog.down('component[itemId=tabpanel]');
                        TYPO3.Dialog.InformationDialog({
                                title: this.localize('image_url'),
                                msg: this.localize('image_url_required'),
@@ -522,9 +555,9 @@ HTMLArea.DefaultImage = Ext.extend(HTMLArea.Plugin, {
                                image = null;
                        }
                        if (image) {
-                               button.setTooltip({ title: this.localize('Modify image') });
+                               button.setTooltip({ text: this.localize('Modify image') });
                        } else {
-                               button.setTooltip({ title: this.localize('Insert image') });
+                               button.setTooltip({ text: this.localize('Insert image') });
                        }
                }
        }
index 9841636..3cfa351 100644 (file)
@@ -21,6 +21,9 @@
                        <trans-unit id="Right:" xml:space="preserve">
                                <source>Right:</source>
                        </trans-unit>
+                       <trans-unit id="Left:" xml:space="preserve">
+                               <source>Left:</source>
+                       </trans-unit>
                        <trans-unit id="Bottom:" xml:space="preserve">
                                <source>Bottom:</source>
                        </trans-unit>
index 33f088d..ac12110 100644 (file)
@@ -27,7 +27,8 @@
 /*
  * Default Inline Plugin for TYPO3 htmlArea RTE
  */
-HTMLArea.DefaultInline = Ext.extend(HTMLArea.Plugin, {
+Ext.define('HTMLArea.DefaultInline', {
+       extend: 'HTMLArea.Plugin',
        /*
         * This function gets called by the class constructor
         */
index 91e0b90..b7f80a6 100644 (file)
@@ -29,7 +29,8 @@
 /*
  * Default Link Plugin for TYPO3 htmlArea RTE
  */
-HTMLArea.DefaultLink = Ext.extend(HTMLArea.Plugin, {
+Ext.define('HTMLArea.DefaultLink', {
+       extend: 'HTMLArea.Plugin',
        /*
         * This function gets called by the class constructor
         */
@@ -83,17 +84,24 @@ HTMLArea.DefaultLink = Ext.extend(HTMLArea.Plugin, {
         * Sets of default configuration values for dialogue form fields
         */
        configDefaults: {
-               combo: {
+               combobox: {
+                       cls: 'htmlarea-combo',
+                       displayField: 'text',
+                       listConfig: {
+                               cls: 'htmlarea-combo-list',
+                               getInnerTpl: function () {
+                                       return '<div data-qtip="{value}" class="htmlarea-combo-list-item">{text}</div>';
+                               }
+                       },
                        editable: true,
+                       forceSelection: true,
+                       helpIcon: true,
+                       queryMode: 'local',
                        selectOnFocus: true,
-                       typeAhead: true,
                        triggerAction: 'all',
-                       forceSelection: true,
-                       mode: 'local',
+                       typeAhead: true,
                        valueField: 'value',
-                       displayField: 'text',
-                       helpIcon: true,
-                       tpl: '<tpl for="."><div ext:qtip="{value}" style="text-align:left;font-size:11px;" class="x-combo-list-item">{text}</div></tpl>'
+                       xtype: 'combobox'
                }
        },
        /*
@@ -135,7 +143,7 @@ HTMLArea.DefaultLink = Ext.extend(HTMLArea.Plugin, {
                                        var selection = this.editor._getSelection();
                                        if (this.editor._selectionEmpty(selection)) {
                                                TYPO3.Dialog.InformationDialog({
-                                                       title: this.getButton(buttonId).tooltip.title,
+                                                       title: this.getButton(buttonId).tooltip.text,
                                                        msg: this.localize('Select some text')
                                                });
                                                break;
@@ -155,7 +163,7 @@ HTMLArea.DefaultLink = Ext.extend(HTMLArea.Plugin, {
                                        // Open dialogue window
                                this.openDialogue(
                                        buttonId,
-                                       this.getButton(buttonId).tooltip.title,
+                                       this.getButton(buttonId).tooltip.text,
                                        this.getWindowDimensions(
                                                {
                                                        width: 470,
@@ -178,14 +186,39 @@ HTMLArea.DefaultLink = Ext.extend(HTMLArea.Plugin, {
         * @return      void
         */
        openDialogue: function (buttonId, title, dimensions) {
-               this.dialog = new Ext.Window({
+                       // Create target options global store
+               var targetStore = Ext.data.StoreManager.lookup('HTMLArea' + '-store-' + this.name + '-target');
+               if (!targetStore) {
+                       targetStore = Ext.create('Ext.data.ArrayStore', {
+                               model: 'HTMLArea.model.Default',
+                               storeId: 'HTMLArea' + '-store-' + this.name + '-target'
+                       });
+                       targetStore.loadData([
+                               {
+                                       text: this.localize('target_none'),
+                                       value: ''
+                               },{
+                                       text: this.localize('target_blank'),
+                                       value: '_blank'
+                               },{
+                                       text: this.localize('target_self'),
+                                       value: '_self'
+                               },{
+                                       text: this.localize('target_top'),
+                                       value: '_top'
+                               },{
+                                       text: this.localize('target_other'),
+                                       value: '_other'
+                               }
+                       ]);
+               }
+               this.dialog = Ext.create('Ext.window.Window', {
                        title: this.localize(title) || title,
                        cls: 'htmlarea-window',
                        border: false,
                        width: dimensions.width,
-                       height: 'auto',
-                               // As of ExtJS 3.1, JS error with IE when the window is resizable
-                       resizable: !Ext.isIE,
+                       layout: 'anchor',
+                       resizable: true,
                        iconCls: this.getButton(buttonId).iconCls,
                        listeners: {
                                afterrender: {
@@ -218,35 +251,24 @@ HTMLArea.DefaultLink = Ext.extend(HTMLArea.Plugin, {
                                                        fieldLabel: this.localize('Title (tooltip):'),
                                                        value: this.parameters.title,
                                                        helpTitle: this.localize('link_title_tooltip')
-                                               }, Ext.apply({
-                                                       xtype: 'combo',
-                                                       fieldLabel: this.localize('Target:'),
-                                                       itemId: 'target',
-                                                       helpTitle: this.localize('link_target_tooltip'),
-                                                       store: new Ext.data.ArrayStore({
-                                                               autoDestroy:  true,
-                                                               fields: [ { name: 'text'}, { name: 'value'}],
-                                                               data: [
-                                                                       [this.localize('target_none'), ''],
-                                                                       [this.localize('target_blank'), '_blank'],
-                                                                       [this.localize('target_self'), '_self'],
-                                                                       [this.localize('target_top'), '_top'],
-                                                                       [this.localize('target_other'), '_other']
-                                                               ]
-                                                       }),
-                                                       listeners: {
-                                                               select: {
-                                                                       fn: this.onTargetSelect
-                                                               }
+                                               }, Ext.applyIf({
+                                                               fieldLabel: this.localize('Target:'),
+                                                               helpTitle: this.localize('link_target_tooltip'),
+                                                               hidden: !this.showTarget,
+                                                               itemId: 'target',
+                                                               listeners: {
+                                                                       select: {
+                                                                               fn: this.onTargetSelect
+                                                                       }
+                                                               },
+                                                               store: targetStore
                                                        },
-                                                       hidden: !this.showTarget
-                                                       }, this.configDefaults['combo'])
-                                               ,{
-                                                       itemId: 'frame',
-                                                       name: 'frame',
+                                                       this.configDefaults['combobox']
+                                               ),{
+                                                       itemId: 'framename',
+                                                       name: 'framename',
                                                        fieldLabel: this.localize('frame'),
                                                        helpTitle: this.localize('frame_help'),
-                                                       hideLabel: true,
                                                        hidden: true
                                                }
                                        ]
@@ -264,16 +286,21 @@ HTMLArea.DefaultLink = Ext.extend(HTMLArea.Plugin, {
         * If the current target is not in the available options, show frame field
         */
        onAfterRender: function (dialog) {
-               var targetCombo = dialog.find('itemId', 'target')[0];
-               if (!targetCombo.hidden && this.parameters.target) {
-                       var frameField = dialog.find('itemId', 'frame')[0];
+               var targetCombo = dialog.down('component[itemId=target]');
+                       // Somehow getStore method got lost...
+               if (!Ext.isFunction(targetCombo.getStore)) {
+                       targetCombo.getStore = function () {
+                               return targetCombo.store;
+                       };
+               }
+               if (!targetCombo.isHidden() && this.parameters.target) {
+                       var frameField = dialog.down('component[itemId=framename]');
                        var index = targetCombo.getStore().find('value', this.parameters.target);
                        if (index == -1) {
                                        // The target is a specific frame name
                                targetCombo.setValue('_other');
                                frameField.setValue(this.parameters.target);
                                frameField.show();
-                               frameField.label.show();
                        } else {
                                targetCombo.setValue(this.parameters.target);
                        }
@@ -282,28 +309,26 @@ HTMLArea.DefaultLink = Ext.extend(HTMLArea.Plugin, {
        /*
         * Handler invoked when a target is selected
         */
-       onTargetSelect: function (combo, record) {
-               var frameField = combo.ownerCt.getComponent('frame');
-               if (record.get('value') == '_other') {
+       onTargetSelect: function (combo, records) {
+               var frameField = combo.ownerCt.getComponent('framename');
+               if (records[0].get('value') == '_other') {
                        frameField.show();
-                       frameField.label.show();
                        frameField.focus();
-               } else if (!frameField.hidden) {
+               } else if (!frameField.isHidden()) {
                        frameField.hide();
-                       frameField.label.hide();
                }
        },
        /*
         * Handler invoked when the OK button is clicked
         */
        onOK: function () {
-               var hrefField = this.dialog.find('itemId', 'href')[0];
+               var hrefField = this.dialog.down('component[itemId=href]');
                var href = hrefField.getValue().trim();
                if (href && href != 'http://') {
-                       var title = this.dialog.find('itemId', 'title')[0].getValue();
-                       var target = this.dialog.find('itemId', 'target')[0].getValue();
+                       var title = this.dialog.down('component[itemId=title]').getValue();
+                       var target = this.dialog.down('component[itemId=target]').getValue();
                        if (target == '_other') {
-                               target = this.dialog.find('itemId', 'frame')[0].getValue().trim();
+                               target = this.dialog.down('component[itemId=framename]').getValue().trim();
                        }
                        this.createLink(href, title, target);
                        this.close();
@@ -402,9 +427,9 @@ HTMLArea.DefaultLink = Ext.extend(HTMLArea.Plugin, {
                                                        node = el;
                                                }
                                                if (node != null && /^a$/i.test(node.nodeName)) {
-                                                       button.setTooltip({ title: this.localize('Modify link') });
+                                                       button.setTooltip({ text: this.localize('Modify link') });
                                                } else {
-                                                       button.setTooltip({ title: this.localize('Insert link') });
+                                                       button.setTooltip({ text: this.localize('Insert link') });
                                                }
                                        }
                                        break;
index 4986dca..3d77b3a 100644 (file)
@@ -27,7 +27,8 @@
 /*
  * DefinitionList Plugin for TYPO3 htmlArea RTE
  */
-HTMLArea.DefinitionList = Ext.extend(HTMLArea.BlockElements, {
+Ext.define('HTMLArea.DefinitionList', {
+       extend: 'HTMLArea.BlockElements',
        /*
         * This function gets called by the class constructor
         */
@@ -123,14 +124,14 @@ HTMLArea.DefinitionList = Ext.extend(HTMLArea.BlockElements, {
                                if (/^(dd|dt)$/i.test(parentElement.nodeName) && this.indentDefinitionList(parentElement, range)) {
                                        break;
                                } else {
-                                       HTMLArea.DefinitionList.superclass.onButtonPress.call(this, editor, id, target, className);
+                                       this.callParent(arguments);
                                }
                                break;
                        case "Outdent" :
                                if (/^(dt)$/i.test(parentElement.nodeName) && this.outdentDefinitionList(selection, range)) {
                                        break;
                                } else {
-                                       HTMLArea.DefinitionList.superclass.onButtonPress.call(this, editor, id, target, className);
+                                       this.callParent(arguments);
                                }
                                break;
                        case "DefinitionList":
@@ -144,7 +145,7 @@ HTMLArea.DefinitionList = Ext.extend(HTMLArea.BlockElements, {
                                this.editor.selectRange(this.editor.moveToBookmark(bookmark));
                                break;
                        default:
-                               HTMLArea.DefinitionList.superclass.onButtonPress.call(this, editor, id, target, className);
+                               this.callParent(arguments);
                }
                return false;
        },
@@ -320,7 +321,7 @@ HTMLArea.DefinitionList = Ext.extend(HTMLArea.BlockElements, {
                                                                && !endBlocks.end.nextSibling) {
                                                        button.setDisabled(false);
                                                } else {
-                                                       HTMLArea.DefinitionList.superclass.onUpdateToolbar.call(this, button, mode, selectionEmpty, ancestors);
+                                                       this.callParent(arguments);
                                                }
                                                break;
                                        case 'DefinitionList':
@@ -331,7 +332,7 @@ HTMLArea.DefinitionList = Ext.extend(HTMLArea.BlockElements, {
                        } else {
                                switch (button.itemId) {
                                        case 'Outdent':
-                                               HTMLArea.DefinitionList.superclass.onUpdateToolbar.call(this, button, mode, selectionEmpty, ancestors);
+                                               this.callParent(arguments);
                                                break;
                                }
                        }
index 5b131ca..966ecf9 100644 (file)
@@ -27,7 +27,8 @@
 /*
  * EditElement plugin for htmlArea RTE
  */
-HTMLArea.EditElement = Ext.extend(HTMLArea.Plugin, {
+Ext.define('HTMLArea.EditElement', {
+       extend: 'HTMLArea.Plugin',
        /*
         * This function gets called by the class constructor
         */
@@ -40,7 +41,7 @@ HTMLArea.EditElement = Ext.extend(HTMLArea.Plugin, {
                 * Registering plugin "About" information
                 */
                var pluginInformation = {
-                       version         : '1.1',
+                       version         : '2.0',
                        developer       : 'Stanislas Rolland',
                        developerUrl    : 'http://www.sjbr.ca/',
                        copyrightOwner  : 'Stanislas Rolland',
@@ -67,17 +68,24 @@ HTMLArea.EditElement = Ext.extend(HTMLArea.Plugin, {
         * Sets of default configuration values for dialogue form fields
         */
        configDefaults: {
-               combo: {
+               combobox: {
+                       cls: 'htmlarea-combo',
+                       displayField: 'text',
+                       listConfig: {
+                               cls: 'htmlarea-combo-list',
+                               getInnerTpl: function () {
+                                       return '<div data-qtip="{value}" class="htmlarea-combo-list-item">{text}</div>';
+                               }
+                       },
                        editable: true,
+                       forceSelection: true,
+                       helpIcon: true,
+                       queryMode: 'local',
                        selectOnFocus: true,
-                       typeAhead: true,
                        triggerAction: 'all',
-                       forceSelection: true,
-                       mode: 'local',
+                       typeAhead: true,
                        valueField: 'value',
-                       displayField: 'text',
-                       helpIcon: true,
-                       tpl: '<tpl for="."><div ext:qtip="{value}" style="text-align:left;font-size:11px;" class="x-combo-list-item">{text}</div></tpl>'
+                       xtype: 'combobox'
                }
        },
        /*
@@ -123,14 +131,13 @@ HTMLArea.EditElement = Ext.extend(HTMLArea.Plugin, {
         * @return      void
         */
        openDialogue: function (buttonId, title, dimensions, tabItems, buttonsConfig) {
-               this.dialog = new Ext.Window({
+               this.dialog = Ext.create('Ext.window.Window', {
                        title: this.getHelpTip('', title),
                        cls: 'htmlarea-window',
                        border: false,
                        width: dimensions.width,
-                       height: 'auto',
-                               // As of ExtJS 3.1, JS error with IE when the window is resizable
-                       resizable: !Ext.isIE,
+                       layout: 'anchor',
+                       resizable: true,
                        iconCls: this.getButton(buttonId).iconCls,
                        listeners: {
                                close: {
@@ -143,17 +150,11 @@ HTMLArea.EditElement = Ext.extend(HTMLArea.Plugin, {
                                activeTab: 0,
                                defaults: {
                                        xtype: 'container',
-                                       layout: 'form',
+                                       layout: 'anchor',
                                        defaults: {
                                                labelWidth: 150
                                        }
                                },
-                               listeners: {
-                                       tabchange: {
-                                               fn: this.syncHeight,
-                                               scope: this
-                                       }
-                               },
                                items: tabItems
                        },
                        buttons: buttonsConfig
@@ -171,10 +172,13 @@ HTMLArea.EditElement = Ext.extend(HTMLArea.Plugin, {
                var tabItems = [];
                var generalTabItemConfig = [];
                if (this.removedFieldsets.indexOf('identification') == -1) {
-                       this.addConfigElement(this.buildIdentificationFieldsetConfig(element), generalTabItemConfig);
+                               this.addConfigElement(this.buildIdentificationFieldsetConfig(element), generalTabItemConfig);
                }
                if (this.removedFieldsets.indexOf('style') == -1 && this.removedProperties.indexOf('className') == -1) {
-                       this.addConfigElement(this.buildClassFieldsetConfig(element), generalTabItemConfig);
+                       this.stylePlugin = this.getPluginInstance(HTMLArea.isBlockElement(element) ? 'BlockStyle' : 'TextStyle');
+                       if (this.stylePlugin) {
+                               this.addConfigElement(this.buildClassFieldsetConfig(element), generalTabItemConfig);
+                       }
                }
                tabItems.push({
                        title: this.localize('general'),
@@ -246,9 +250,48 @@ HTMLArea.EditElement = Ext.extend(HTMLArea.Plugin, {
         */
        buildClassFieldsetConfig: function (element) {
                var itemsConfig = [];
-               var stylingCombo = this.buildStylingField('className', 'className', 'className');
-               this.setStyleOptions(stylingCombo, element);
-               itemsConfig.push(stylingCombo);
+                       // Create global style store if it does not exist already
+               var styleStore = Ext.data.StoreManager.lookup(this.editorId + '-store-' + this.stylePlugin.name);
+               if (!styleStore) {
+                       styleStore = Ext.create('Ext.data.ArrayStore', {
+                               model: 'HTMLArea.model.' + this.stylePlugin.name,
+                               storeId: this.editorId + '-store-' + this.stylePlugin.name,
+                               data: []
+                       });
+               }
+               function initStyleCombo (combo) {
+                       var nodeName = element.nodeName.toLowerCase();
+                       var classNames = HTMLArea.DOM.getClassNames(element);
+                               // Somehow getStore method got lost...
+                       if (!Ext.isFunction(combo.getStore)) {
+                               combo.getStore = function () {
+                                       return combo.store;
+                               };
+                       }
+                       this.stylePlugin.buildDropDownOptions(combo, nodeName);
+                       this.stylePlugin.setSelectedOption(combo, classNames, 'noUnknown');
+               }
+               itemsConfig.push(Ext.applyIf(
+                       {
+                               fieldLabel: this.getHelpTip('className', 'className'),
+                               listConfig: {
+                                       cls: 'htmlarea-combo-list',
+                                       getInnerTpl: function () {
+                                               return '<div data-qtip="{value}" class="htmlarea-combo-list-item">{text}</div>';
+                                       }
+                               },
+                               itemId: 'className',
+                               store: styleStore,
+                               width: ((this.properties['className'] && this.properties['className'].width) ? this.properties['className'].width : 300),
+                               listeners: {
+                                       afterrender: {
+                                               fn: initStyleCombo,
+                                               scope: this
+                                       }
+                               }
+                       },
+                       this.configDefaults['combobox']
+               ));
                return {
                        xtype: 'fieldset',
                        title: this.localize('className'),
@@ -260,48 +303,6 @@ HTMLArea.EditElement = Ext.extend(HTMLArea.Plugin, {
                };
        },
        /*
-        * This function builds a style selection field
-        *
-        * @param       string          fieldName: the name of the field
-        * @param       string          fieldLabel: the label for the field
-        * @param       string          cshKey: the csh key
-        *
-        * @return      object          the style selection field object
-        */
-       buildStylingField: function (fieldName, fieldLabel, cshKey) {
-               return new Ext.form.ComboBox(Ext.apply({
-                       xtype: 'combo',
-                       itemId: fieldName,
-                       fieldLabel: this.getHelpTip(fieldLabel, cshKey),
-                       width: ((this.properties['className'] && this.properties['className'].width) ? this.properties['className'].width : 300),
-                       store: new Ext.data.ArrayStore({
-                               autoDestroy:  true,
-                               fields: [ { name: 'text'}, { name: 'value'}, { name: 'style'} ],
-                               data: [[this.localize('No style'), 'none']]
-                       })
-                       }, {
-                       tpl: '<tpl for="."><div ext:qtip="{value}" style="{style}text-align:left;font-size:11px;" class="x-combo-list-item">{text}</div></tpl>'
-                       }, this.configDefaults['combo']
-               ));
-       },
-       /*
-        * This function populates the class store and sets the selected option
-        *
-        * @param       object:         comboBox: the combobox object
-        * @param       object          element: the element being edited, if any
-        *
-        * @return      object          the fieldset configuration object
-        */
-       setStyleOptions: function (comboBox, element) {
-               var nodeName = element.nodeName.toLowerCase();
-               this.stylePlugin = this.getPluginInstance(HTMLArea.isBlockElement(element) ? 'BlockStyle' : 'TextStyle');
-               if (comboBox && this.stylePlugin) {
-                       var classNames = HTMLArea.DOM.getClassNames(element);
-                       this.stylePlugin.buildDropDownOptions(comboBox, nodeName);
-                       this.stylePlugin.setSelectedOption(comboBox, classNames, 'noUnknown');
-               }
-       },
-       /*
         * This function builds the configuration object for the Language fieldset
         *
         * @param       object          element: the element being edited, if any
@@ -320,48 +321,76 @@ HTMLArea.EditElement = Ext.extend(HTMLArea.Plugin, {
                        function initLanguageStore (store) {
                                if (selectedLanguage !== 'none') {
                                        store.removeAt(0);
-                                       store.insert(0, new store.recordType({
+                                       store.insert(0, {
                                                text: languagePlugin.localize('Remove language mark'),
                                                value: 'none'
-                                       }));
+                                       });
                                }
                        }
-                       var languageStore = new Ext.data.JsonStore({
-                               autoDestroy:  true,
-                               autoLoad: true,
-                               root: 'options',
-                               fields: [ { name: 'text'}, { name: 'value'} ],
-                               url: languageConfigurationUrl,
-                               listeners: {
-                                       load: initLanguageStore
-                               }
-                       });
-                       itemsConfig.push(Ext.apply({
-                               xtype: 'combo',
-                               fieldLabel: languagePlugin.getHelpTip('languageCombo', 'Language'),
-                               itemId: 'lang',
-                               store: languageStore,
-                               width: ((this.properties['language'] && this.properties['language'].width) ? this.properties['language'].width : 200),
-                               value: selectedLanguage
-                       }, this.configDefaults['combo']));
+                               // Create global language store if it does not exist already
+                       var languageStore = Ext.data.StoreManager.lookup(this.editorId + '-store-' + languagePlugin.name);
+                       if (languageStore) {
+                               initLanguageStore(languageStore);
+                       } else {
+                               languageStore = Ext.create('Ext.data.Store', {
+                                       autoLoad: true,
+                                       model: 'HTMLArea.model.default',
+                                       listeners: {
+                                               load: initLanguageStore
+                                       },
+                                       proxy: {
+                                               type: 'ajax',
+                                               url: languageConfigurationUrl,
+                                               reader: {
+                                                       type: 'json',
+                                                       root: 'options'
+                                               }
+                                       },
+                                       storeId: this.editorId + '-store-' + languagePlugin.name
+                               });
+                       }
+                       itemsConfig.push(Ext.applyIf(
+                               {
+                                       fieldLabel: languagePlugin.getHelpTip('languageCombo', 'Language'),
+                                       itemId: 'lang',
+                                       store: languageStore,
+                                       width: ((this.properties['language'] && this.properties['language'].width) ? this.properties['language'].width : 300),
+                                       value: selectedLanguage
+                               },
+                               this.configDefaults['combobox']
+                       ));
                }
                if (this.removedProperties.indexOf('direction') == -1) {
-                       itemsConfig.push(Ext.apply({
-                               xtype: 'combo',
-                               fieldLabel: languagePlugin.getHelpTip('directionCombo', 'Text direction'),
-                               itemId: 'dir',
-                               store: new Ext.data.ArrayStore({
-                                       autoDestroy:  true,
-                                       fields: [ { name: 'text'}, { name: 'value'}],
-                                       data: [
-                                               [languagePlugin.localize('Not set'), 'not set'],
-                                               [languagePlugin.localize('RightToLeft'), 'rtl'],
-                                               [languagePlugin.localize('LeftToRight'), 'ltr']
-                                       ]
-                               }),
-                               width: ((this.properties['direction'] && this.properties['dirrection'].width) ? this.properties['direction'].width : 200),
-                               value: !Ext.isEmpty(element) && element.dir ? element.dir : 'not set'
-                       }, this.configDefaults['combo']));
+                               // Create direction options global store
+                       var directionStore = Ext.data.StoreManager.lookup('HTMLArea' + '-store-' + languagePlugin.name + '-direction');
+                       if (!directionStore) {
+                               directionStore = Ext.create('Ext.data.ArrayStore', {
+                                       model: 'HTMLArea.model.Default',
+                                       storeId: 'HTMLArea' + '-store-' + languagePlugin.name + '-direction'
+                               });
+                               directionStore.loadData([
+                                       {
+                                               text: languagePlugin.localize('Not set'),
+                                               value: 'not set'
+                                       },{
+                                               text: languagePlugin.localize('RightToLeft'),
+                                               value: 'rtl'
+                                       },{
+                                               text: languagePlugin.localize('LeftToRight'),
+                                               value: 'ltr'
+                                       }
+                               ]);
+                       }
+                       itemsConfig.push(Ext.applyIf(
+                               {
+                                       fieldLabel: languagePlugin.getHelpTip('directionCombo', 'Text direction'),
+                                       itemId: 'dir',
+                                       store: directionStore,
+                                       value: !Ext.isEmpty(element) && element.dir ? element.dir : 'not set',
+                                       width: ((this.properties['direction'] && this.properties['dirrection'].width) ? this.properties['direction'].width : 300)
+                               },
+                               this.configDefaults['combobox']
+                       ));
                }
                return {
                        xtype: 'fieldset',
@@ -428,11 +457,11 @@ HTMLArea.EditElement = Ext.extend(HTMLArea.Plugin, {
         */
        okHandler: function (button, event) {
                this.restoreSelection();
-               var textFields = this.dialog.findByType('textfield');
+               var textFields = this.dialog.query('textfield');
                Ext.each(textFields, function (field) {
                        this.element.setAttribute(field.getItemId(), field.getValue());
                }, this);
-               var comboFields = this.dialog.findByType('combo');
+               var comboFields = this.dialog.query('combobox');
                Ext.each(comboFields, function (field) {
                        var itemId = field.getItemId();
                        var value = field.getValue();
index 315292e..5a20d1f 100644 (file)
@@ -27,7 +27,8 @@
 /*
  * EditorMode Plugin for TYPO3 htmlArea RTE
  */
-HTMLArea.EditorMode = Ext.extend(HTMLArea.Plugin, {
+Ext.define('HTMLArea.EditorMode', {
+       extend: 'HTMLArea.Plugin',
        /*
         * This function gets called by the class constructor
         */
index 86593fb..515e0d8 100644 (file)
@@ -30,7 +30,8 @@
 /*
  * Find and Replace Plugin for TYPO3 htmlArea RTE
  */
-HTMLArea.FindReplace = Ext.extend(HTMLArea.Plugin, {
+Ext.define('HTMLArea.FindReplace', {
+       extend: 'HTMLArea.Plugin',
        /*
         * This function gets called by the class constructor
         */
@@ -116,14 +117,13 @@ HTMLArea.FindReplace = Ext.extend(HTMLArea.Plugin, {
         * @return      void
         */
        openDialogue: function (buttonId, title, dimensions) {
-               this.dialog = new Ext.Window({
+               this.dialog = Ext.create('Ext.window.Window', {
                        title: this.localize(title),
                        cls: 'htmlarea-window',
                        border: false,
                        width: dimensions.width,
-                       height: 'auto',
-                               // As of ExtJS 3.1, JS error with IE when the window is resizable
-                       resizable: !Ext.isIE,
+                       layout: 'anchor',
+                       resizable: true,
                        iconCls: this.getButton(buttonId).iconCls,
                        listeners: {
                                close: {
@@ -266,11 +266,11 @@ HTMLArea.FindReplace = Ext.extend(HTMLArea.Plugin, {
         * Handler invoked when the replace all checkbox is checked
         */
        requestReplacement: function () {
-               if (!this.dialog.find('itemId', 'replacement')[0].getValue() && this.dialog.find('itemId', 'replaceAll')[0].getValue()) {
+               if (!this.dialog.down('component[itemId=replacement]').getValue() && this.dialog.down('component[itemId=replaceAll]').getValue()) {
                        TYPO3.Dialog.InformationDialog({
                                title: this.getButton('FindReplace').tooltip.title,
                                msg: this.localize('Inform a replacement word'),
-                               fn: function () { this.dialog.find('itemId', 'replacement')[0].focus(); },
+                               fn: function () { this.dialog.down('component[itemId=replacement]').focus(); },
                                scope: this
                        });
                }
@@ -280,11 +280,11 @@ HTMLArea.FindReplace = Ext.extend(HTMLArea.Plugin, {
         * Handler invoked when the 'Next' button is pressed
         */
        onNext: function () {
-               if (!this.dialog.find('itemId', 'pattern')[0].getValue()) {
+               if (!this.dialog.down('component[itemId=pattern]').getValue()) {
                        TYPO3.Dialog.InformationDialog({
                                title: this.getButton('FindReplace').tooltip.title,
                                msg: this.localize('Enter the text you want to find'),
-                               fn: function () { this.dialog.find('itemId', 'pattern')[0].focus(); },
+                               fn: function () { this.dialog.down('component[itemId=pattern]').focus(); },
                                scope: this
                        });
                        return false;
@@ -298,7 +298,7 @@ HTMLArea.FindReplace = Ext.extend(HTMLArea.Plugin, {
                ];
                var params = {};
                Ext.each(fields, function (field) {
-                       params[field] = this.dialog.find('itemId', field)[0].getValue();
+                       params[field] = this.dialog.down('component[itemId=' + field + ']').getValue();
                }, this);
                this.search(params);
                return false;
@@ -458,6 +458,8 @@ HTMLArea.FindReplace = Ext.extend(HTMLArea.Plugin, {
                if (this.buffer != null) {
                        var transp = this.editor.getInnerHTML();
                        this.editor.setHTML(this.buffer);
+                               // Initialize a collapsed selection at the beginning of content
+                       this.editor.selectNode(this.editor.document.body, true);
                        this.buffer = transp;
                        this.disableActions('clear', true);
                }
@@ -470,7 +472,7 @@ HTMLArea.FindReplace = Ext.extend(HTMLArea.Plugin, {
         */
        disableActions: function (actions, disabled) {
                Ext.each(actions.split(/[,; ]+/), function (action) {
-                               this.dialog.find('itemId', action)[0].setDisabled(disabled);
+                       this.dialog.down('component[itemId=' + action + ']').setDisabled(disabled);
                }, this);
        },
        /*
@@ -486,21 +488,25 @@ HTMLArea.FindReplace = Ext.extend(HTMLArea.Plugin, {
         */
        onCancel: function () {
                this.clearDoc();
+                       // Initialize a collapsed selection at the beginning of content
+               this.editor.selectNode(this.editor.document.body, true);
                var plugin = this.getPluginInstance('UndoRedo');
                if (plugin) {
                        plugin.start();
                }
-               HTMLArea.FindReplace.superclass.onCancel.call(this);
+               this.callParent(arguments);
        },
        /*
         * Clear the document before leaving on window close handle
         */
        onClose: function () {
                this.clearDoc();
+                       // Initialize a collapsed selection at the beginning of content
+               this.editor.selectNode(this.editor.document.body, true);
                var plugin = this.getPluginInstance('UndoRedo');
                if (plugin) {
                        plugin.start();
                }
-               HTMLArea.FindReplace.superclass.onClose.call(this);
+               this.callParent(arguments);
        }
 });