Added feature #12930: htmlArea: Resizable RTE area
authorStanislas Rolland <typo3@sjbr.ca>
Sat, 5 Dec 2009 05:15:50 +0000 (05:15 +0000)
committerStanislas Rolland <typo3@sjbr.ca>
Sat, 5 Dec 2009 05:15:50 +0000 (05:15 +0000)
git-svn-id: https://svn.typo3.org/TYPO3v4/Core/trunk@6630 709f56b5-9817-0410-a4d7-c38de5d9e867

ChangeLog
typo3/sysext/rtehtmlarea/ChangeLog
typo3/sysext/rtehtmlarea/htmlarea/htmlarea.js
typo3/sysext/rtehtmlarea/htmlarea/plugins/EditorMode/editor-mode.js
typo3/sysext/rtehtmlarea/htmlarea/skins/default/htmlarea.css
typo3/sysext/rtehtmlarea/htmlarea/skins/default/images/resize.gif [new file with mode: 0644]
typo3/sysext/rtehtmlarea/pi2/class.tx_rtehtmlarea_pi2.php
typo3/sysext/t3skin/rtehtmlarea/htmlarea.css
typo3/sysext/t3skin/rtehtmlarea/images/resize.gif [new file with mode: 0644]

index 3c6d0d7..dff8354 100755 (executable)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2009-12-05  Stanislas Rolland  <typo3@sjbr.ca>
+
+       * Added feature #12930: htmlArea: Resizable RTE area
+
 2009-12-02  Steffen Kamper  <info@sk-typo3.de>
 
        * Fixed bug #12899: Wrong usage of CDATA raise javascript error
index 32a35a0..a0f0ecd 100644 (file)
@@ -1,3 +1,7 @@
+2009-12-05  Stanislas Rolland  <typo3@sjbr.ca>
+
+       * Added feature #12930: htmlArea: Resizable RTE area
+
 2009-11-24  Stanislas Rolland  <typo3@sjbr.ca>
 
        * Updated htmlArea RTE manual.
index d23c05d..ef09941 100644 (file)
@@ -794,21 +794,30 @@ HTMLArea.toolBarButtonHandler = function(ev) {
  * Create the htmlArea iframe and replace the textarea with it.
  */
 HTMLArea.prototype.generate = function () {
-
-               // get the textarea and hide it
-       var textarea = this._textArea;
-       textarea.style.display = "none";
-
-               // create the editor framework and insert the editor before the textarea
-       var htmlarea = document.createElement("div");
-       htmlarea.className = "htmlarea";
-       htmlarea.style.width = textarea.style.width;
-       this._htmlArea = htmlarea;
-       textarea.parentNode.insertBefore(htmlarea, textarea);
-
-       if(textarea.form) {
-                       // we have a form, on reset, re-initialize the HTMLArea content and update the toolbar
-               var f = textarea.form;
+       var self = this;
+               // Get the textarea, hide it and make it resizable
+       this.textArea = Ext.get(this._textArea).setVisibilityMode(2).setVisible(false);
+       if (TYPO3.settings.textareaResize) {
+               this.textArea.addClass('resizable');
+               this.textAreaResizer = new Ext.Resizable(this.textArea, {
+                       minWidth:  300,
+                       minHeight: 200,
+                       maxHeight: TYPO3.settings.textareaMaxHeight,
+                       dynamic:   true
+               });
+               this.textAreaResizer.on('resize', function(ev) { self.resizeOnTextAreaChange(2); });
+       }
+
+               // Create the editor framework and insert it before the textarea
+       this.htmlArea = Ext.DomHelper.insertBefore(this.textArea, {
+               tag: 'div',
+               cls: 'htmlarea'
+       }, true).setWidth(this.textArea.getStyle('width'));
+       this._htmlArea = this.htmlArea.dom;
+
+               // If we have a form, on reset, re-initialize the HTMLArea content and update the toolbar
+       if (this.textArea.dom.form) {
+               var f = this.textArea.dom.form;
                if (typeof(f.onreset) == "function") {
                        var funcref = f.onreset;
                        if (typeof(f.__msh_prevOnReset) == "undefined") f.__msh_prevOnReset = [];
@@ -818,27 +827,33 @@ HTMLArea.prototype.generate = function () {
                HTMLArea._addEvent(f, "reset", HTMLArea.resetHandler);
        }
 
-               // create & append the toolbar
+               // Create & append the toolbar
        this._createToolbar();
        HTMLArea._appendToLog("[HTMLArea::generate]: Toolbar successfully created.");
 
-               // create and append the IFRAME
-       var iframe = document.createElement("iframe");
-       if (HTMLArea.is_gecko && !HTMLArea.is_safari && !HTMLArea.is_opera) {
-               iframe.setAttribute("src", "javascript:void(0);");
-       } else {
-               iframe.setAttribute("src", (HTMLArea.is_opera?_typo3_host_url:"") + _editor_url + "popups/blank.html");
-       }
-       iframe.className = "editorIframe";
-       if (!this.getPluginInstance("StatusBar")) {
-               iframe.className += " noStatusBar";
+               // Create the editor iframe and append it to the toolbar
+       this.iframe = Ext.DomHelper.append(this.htmlArea, {
+                       tag: 'iframe',
+                       cls: 'editorIframe',
+                       src: (HTMLArea.is_gecko && !HTMLArea.is_safari && !HTMLArea.is_opera) ? 'javascript:void(0);' : (HTMLArea.is_opera?_typo3_host_url:'') + _editor_url + 'popups/blank.html'
+       }, true);
+       if (!this.getPluginInstance('StatusBar')) {
+               this.iframe.addClass('noStatusBar');
        }
-       htmlarea.appendChild(iframe);
-       this._iframe = iframe;
+       this._iframe = this.iframe.dom;
        HTMLArea._appendToLog("[HTMLArea::generate]: Editor iframe successfully created.");
+               // Make the editor framework resizable
+       if (TYPO3.settings.textareaResize) {
+               this.htmlArea.addClass('resizable');
+               var dimensions = this.getDimensions();
+               this.htmlAreaResizer = new Ext.Resizable(this.htmlArea, {
+                       maxHeight: parseInt(TYPO3.settings.textareaMaxHeight) + dimensions.toolbar.height + dimensions.statusbar.height,
+                       dynamic:   false
+               });
+               this.htmlAreaResizer.on('resize', function(ev) { self.resizeOnHtmlAreaChange(2); });
+       }
        if (HTMLArea.is_opera) {
-               var self = this;
-               this._iframe.onload = function() { self.initIframe(); };
+               this.iframe.on('load', function() { self.initIframe(); } , this);
        } else {
                this.initIframe();
        }
@@ -846,6 +861,58 @@ HTMLArea.prototype.generate = function () {
 };
 
 /*
+ * Resize the editor framework and the iframe when the textarea was resized
+ */
+HTMLArea.prototype.resizeOnTextAreaChange = function(diff) {
+               // Set width first as it may change the height of the toolbar and of the statusbar
+       var width = this.textArea.getStyle('width');
+       if (width.indexOf('%') == -1) {
+               width = (parseInt(width) + diff) + 'px';
+       }
+       this.iframe.setStyle('width', HTMLArea.is_opera ? width : '100%');
+       this.htmlArea.setStyle('width', width);
+               // Set height
+       var dimensions = this.getDimensions();
+       var height = this.textArea.getStyle('height');
+       if (height.indexOf('%') == -1) {
+               height = (parseInt(height) + diff) + 'px';
+       }
+       this.iframe.setStyle('height', height);
+       this.htmlArea.setStyle('height', (dimensions.toolbar.height + dimensions.statusbar.height) + 'px');
+};
+
+/*
+ * Resize the textarea and iframe when the htmlArea was resized
+ */
+HTMLArea.prototype.resizeOnHtmlAreaChange = function(diff) {
+               // Set width first as it may change the height of the toolbar and of the statusbar
+       var width = this.htmlArea.getStyle('width');
+               // Do not shrink narrower than configured textarea
+       if (parseInt(width) < this.textAreaResizer.minWidth + diff) {
+               width = (this.textAreaResizer.minWidth + diff) + 'px';
+               this.htmlArea.setStyle('width', width);
+       }
+       if (width.indexOf('%') == -1) {
+               width = (parseInt(width) - diff) + 'px';
+       }
+       this.textArea.setStyle('width', width);
+               // Set height
+       var height = this.iframe.getStyle('height');
+       if (height.indexOf('%') == -1) {
+               var dimensions = this.getDimensions();
+               height = parseInt(this.htmlArea.getStyle('height')) - dimensions.toolbar.height - dimensions.statusbar.height;
+                       // Do not shrink shorter than configured textarea
+               if (height < this.textAreaResizer.minHeight + diff) {
+                       height = this.textAreaResizer.minHeight + diff;
+                       this.htmlArea.setStyle('height', (height + dimensions.toolbar.height + dimensions.statusbar.height) + 'px');
+               }
+               this.iframe.setStyle('height', height + 'px');
+               height = (height - diff) + 'px';
+       }
+       this.textArea.setStyle('height', height);
+};
+
+/*
  * Size the iframe according to user's prefs or initial textarea
  */
 HTMLArea.prototype.sizeIframe = function(diff) {
@@ -857,7 +924,8 @@ HTMLArea.prototype.sizeIframe = function(diff) {
        this.config.height = (this.config.height == "auto") ? this._textArea.style.height : this.config.height;
        var iframeHeight = this.config.height;
        var textareaHeight = this.config.height;
-       if (textareaHeight.indexOf("%") == -1) {
+       var htmlAreaHeight = this.config.height;
+       if (this.config.height.indexOf("%") == -1) {
                iframeHeight = parseInt(iframeHeight) - diff;
                if (this.config.sizeIncludesToolbar) {
                        this._initialToolbarOffsetHeight = this._initialToolbarOffsetHeight ? this._initialToolbarOffsetHeight : dimensions.toolbar.height;
@@ -867,6 +935,7 @@ HTMLArea.prototype.sizeIframe = function(diff) {
                if (iframeHeight < 0) {
                        iframeHeight = 0;
                }
+               htmlAreaHeight = (iframeHeight + dimensions.toolbar.height + dimensions.statusbar.height) + 'px';
                textareaHeight = (iframeHeight - 4);
                if (textareaHeight < 0) {
                        textareaHeight = 0;
@@ -876,6 +945,7 @@ HTMLArea.prototype.sizeIframe = function(diff) {
        }
        this._iframe.style.height = iframeHeight;
        this._textArea.style.height = textareaHeight;
+       this.htmlArea.setStyle('height', htmlAreaHeight);
                // Set width
        this.config.width = (this.config.width == "auto") ? this._textArea.style.width : this.config.width;
        var textareaWidth = this.config.width;
index dfc2219..158c3e2 100644 (file)
@@ -158,6 +158,9 @@ EditorMode = HTMLArea.Plugin.extend({
                        case "docnotwellformedmode":
                                this.textArea.value = this.getHTML();
                                editor._iframe.style.display = "none";
+                               var dimensions = editor.getDimensions();
+                               editor.htmlArea.setStyle('height', (dimensions.toolbar.height + dimensions.statusbar.height) + 'px');
+                               editor.htmlArea.removeClass('resizable');
                                this.textArea.style.display = "block";
                                this.editorMode = "textmode";
                                break;
@@ -173,6 +176,9 @@ EditorMode = HTMLArea.Plugin.extend({
                                }
                                this.textArea.style.display = "none";
                                editor._iframe.style.display = "block";
+                               var dimensions = editor.getDimensions();
+                               editor.htmlArea.setStyle('height', (parseInt(editor.iframe.getStyle('height')) + dimensions.toolbar.height + dimensions.statusbar.height) + 'px');
+                               editor.htmlArea.addClass('resizable');
                                if (HTMLArea.is_gecko && !HTMLArea.is_safari && !HTMLArea.is_opera) {
                                        editor._doc.designMode = "on";
                                }
index a7e42d9..072d242 100644 (file)
@@ -3,6 +3,14 @@
        background-color:#fff;
        margin:0;padding:0;
 }
+.resizable {
+       background-color:transparent;
+       padding-right:7px;
+       padding-bottom:6px;
+       background-image: url("images/resize.gif");
+       background-position: bottom right;
+       background-repeat: no-repeat;
+}
 .pleasewait {
        position:relative;top:0px;text-align:left;
        font-size:8pt;
diff --git a/typo3/sysext/rtehtmlarea/htmlarea/skins/default/images/resize.gif b/typo3/sysext/rtehtmlarea/htmlarea/skins/default/images/resize.gif
new file mode 100644 (file)
index 0000000..89b82d7
Binary files /dev/null and b/typo3/sysext/rtehtmlarea/htmlarea/skins/default/images/resize.gif differ
index b220eb5..dd20224 100644 (file)
@@ -217,14 +217,24 @@ class tx_rtehtmlarea_pi2 extends tx_rtehtmlarea_base {
                 * LOAD JS, CSS and more
                 * =======================================
                 */
+               $pageRenderer = $GLOBALS['TSFE']->getPageRenderer();
+               $pageRenderer->setBackPath(TYPO3_mainDir);
                        // Preloading the pageStyle and including RTE skin stylesheets
                $this->addPageStyle();
                $this->addSkin();
+               $pageRenderer->addCssFile($this->hostURL . '/t3lib/js/extjs/ux/resize.css');
                        // Loading JavaScript files and code
+               $pageRenderer->loadExtJs();
+               $pageRenderer->addJsFile($this->hostURL . '/t3lib/js/extjs/ux/ext.resizable.js');
                if ($this->TCEform->RTEcounter == 1) {
                        $this->TCEform->additionalJS_pre['rtehtmlarea-loadJScode'] = $this->loadJScode($this->TCEform->RTEcounter);
                }
                $this->TCEform->additionalJS_initial = $this->loadJSfiles($this->TCEform->RTEcounter);
+               $resizableSettings = array(
+                       'textareaResize' => true,
+                       'textareaMaxHeight' => '600'
+               );
+               $pageRenderer->addInlineSettingArray('', $resizableSettings);
 
                /* =======================================
                 * DRAW THE EDITOR
index dfc3a65..9e87c72 100644 (file)
@@ -4,6 +4,14 @@
        background-color:#fff;
        margin:0;padding:0;
 }
+.resizable {
+       background-color:transparent;
+       padding-right:7px;
+       padding-bottom:6px;
+       background-image: url("images/resize.gif");
+       background-position: bottom right;
+       background-repeat: no-repeat;
+}
 .pleasewait {
        position:relative;top:0px;text-align:left;
        font-size:10px;
diff --git a/typo3/sysext/t3skin/rtehtmlarea/images/resize.gif b/typo3/sysext/t3skin/rtehtmlarea/images/resize.gif
new file mode 100644 (file)
index 0000000..89b82d7
Binary files /dev/null and b/typo3/sysext/t3skin/rtehtmlarea/images/resize.gif differ