[TASK] RTE: Migrate outer editor framework to plain JavaScript 77/35277/3
authorStanislas Rolland <typo3@sjbr.ca>
Wed, 10 Dec 2014 23:20:10 +0000 (18:20 -0500)
committerStanislas Rolland <typo3@sjbr.ca>
Wed, 10 Dec 2014 23:36:59 +0000 (00:36 +0100)
Replace the extended Ext.Container with plain JavaScript.
Use jQuery UI Resizable in replacement of Ext.Resizable.

Releases: master
Resolves: #63757
Change-Id: I86625b28228c30cdb7524f49014101a40351d17e
Reviewed-on: http://review.typo3.org/35277
Reviewed-by: Stanislas Rolland <typo3@sjbr.ca>
Tested-by: Stanislas Rolland <typo3@sjbr.ca>
typo3/sysext/rtehtmlarea/Classes/RteHtmlAreaBase.php
typo3/sysext/rtehtmlarea/Resources/Public/JavaScript/HTMLArea/DOM/DOM.js
typo3/sysext/rtehtmlarea/Resources/Public/JavaScript/HTMLArea/Editor/Editor.js
typo3/sysext/rtehtmlarea/Resources/Public/JavaScript/HTMLArea/Editor/Framework.js
typo3/sysext/rtehtmlarea/Resources/Public/JavaScript/HTMLArea/Editor/Iframe.js
typo3/sysext/rtehtmlarea/Resources/Public/JavaScript/HTMLArea/Editor/StatusBar.js
typo3/sysext/rtehtmlarea/Resources/Public/JavaScript/HTMLArea/Util/Resizable.js [new file with mode: 0644]
typo3/sysext/rtehtmlarea/Resources/Public/JavaScript/HTMLArea/Util/Util.js

index 0320bfe..7e1566e 100644 (file)
@@ -808,6 +808,7 @@ class RteHtmlAreaBase extends \TYPO3\CMS\Backend\Rte\AbstractRte {
                        'UserAgent/UserAgent',
                        'Util/Util',
                        'Util/Color',
+                       'Util/Resizable',
                        'Util/Tips',
                        'Util/TYPO3',
                        'Ajax/Ajax',
index 7941ce0..e9324b6 100644 (file)
@@ -494,6 +494,51 @@ define('TYPO3/CMS/Rtehtmlarea/HTMLArea/DOM/DOM',
                                }
                        }
                        return absoluteUrl;
+               },
+
+               /**
+                * Get the position of a node
+                *
+                * @param object node
+                * @return object left and top coordinates
+                */
+               getPosition: function (node) {
+                       var x = 0, y = 0;
+                       while (node && !isNaN(node.offsetLeft) && !isNaN(node.offsetTop)) {
+                               x += node.offsetLeft - node.scrollLeft;
+                               y += node.offsetTop - node.scrollTop;
+                               node = node.offsetParent;
+                       }
+                       return { x: x, y: y };
+               },
+
+               /**
+                * Get the current size of a node
+                *
+                * @param object node
+                * @return object width and height
+                */
+               getSize: function (node) {
+                       return {
+                               width:  Math.max(node.offsetWidth, node.clientWidth) || 0,
+                               height: Math.max(node.offsetHeight, node.clientHeight) || 0
+                       }
+               },
+
+               /**
+                * Set the size of a node
+                *
+                * @param object node
+                * @param object size: width and height
+                * @return void
+                */
+               setSize: function (node, size) {
+                       if (typeof size.width !== 'undefined') {
+                               node.style.width = size.width + 'px';
+                       }
+                       if (typeof size.height !== 'undefined') {
+                               node.style.height = size.height + 'px';
+                       }
                }
        };
 
index a6126f7..593a4e8 100644 (file)
@@ -181,7 +181,6 @@ define('TYPO3/CMS/Rtehtmlarea/HTMLArea/Editor/Editor',
                // Create the editor framework
                this.htmlArea = new Framework({
                        id: this.editorId + '-htmlArea',
-                       layout: 'anchor',
                        cls: 'htmlarea',
                        editorId: this.editorId,
                        textArea: this.textArea,
@@ -195,13 +194,13 @@ define('TYPO3/CMS/Rtehtmlarea/HTMLArea/Editor/Editor',
                                // The toolbar
                                id: this.editorId + '-toolbar',
                                itemId: 'toolbar',
-                               anchor: '100%',
                                layout: 'form',
                                cls: 'toolbar',
                                editorId: this.editorId
                                }),
                                new Iframe({
                                        // The iframe
+                                       id: this.editorId + '-iframe',
                                        itemId: 'iframe',
                                        width: (this.textAreaInitialSize.width.indexOf('%') === -1) ? parseInt(this.textAreaInitialSize.width) : 300,
                                        height: parseInt(this.textAreaInitialSize.height),
@@ -215,11 +214,10 @@ define('TYPO3/CMS/Rtehtmlarea/HTMLArea/Editor/Editor',
                                        nestedParentElements: this.nestedParentElements,
                                        editorId: this.editorId
                                }),
-                               {
+                               new Ext.BoxComponent({
                                        // Box container for the textarea
-                                       xtype: 'box',
+                                       id: this.editorId + '-textAreaContainer',
                                        itemId: 'textAreaContainer',
-                                       anchor: '100%',
                                        width: (this.textAreaInitialSize.width.indexOf('%') === -1) ? parseInt(this.textAreaInitialSize.width) : 300,
                                        // Let the framework swallow the textarea and throw it back
                                        listeners: {
@@ -238,23 +236,28 @@ define('TYPO3/CMS/Rtehtmlarea/HTMLArea/Editor/Editor',
                                                        },
                                                        single: true,
                                                        scope: this
+                                               },
+                                               show: {
+                                                       fn: function (textAreaContainer) {
+                                                               Event.trigger(textAreaContainer, 'HTMLAreaEventTextAreaContainerShow');
+                                                       }
                                                }
                                        }
-                               },
+                               }),
                                new StatusBar({
                                        // The status bar
-                                       anchor: '100%',
+                                       id: this.editorId + '-statusBar',
+                                       itemId: 'statusBar',
                                        cls: 'statusBar',
-                                       editorId: this.editorId,
-                                       itemId: 'statusBar'
+                                       editorId: this.editorId
                                })
                        ]
                });
                // Set some references
-               this.toolbar = this.htmlArea.getComponent('toolbar');
-               this.statusBar = this.htmlArea.getComponent('statusBar');
-               this.iframe = this.htmlArea.getComponent('iframe');
-               this.textAreaContainer = this.htmlArea.getComponent('textAreaContainer');
+               this.toolbar = this.htmlArea.getToolbar();
+               this.iframe = this.htmlArea.getIframe();
+               this.textAreaContainer = this.htmlArea.getTextAreaContainer();
+               this.statusBar = this.htmlArea.getStatusBar();
                // Get triggered when the framework becomes ready
                var self = this;
                Event.one(this.htmlArea, 'HTMLAreaEventFrameworkReady', function (event) { Event.stopEvent(event); self.onFrameworkReady(); return false; });
index 08fc97b..a71131a 100644 (file)
  * The TYPO3 project - inspiring people to share!
  */
 /**
- * Framework extends Ext.Panel and is the visual component of the Editor and contains the tool bar, the iframe, the textarea and the status bar
+ * Framework is the visual component of the Editor and contains the tool bar, the iframe, the textarea and the status bar
  */
 define('TYPO3/CMS/Rtehtmlarea/HTMLArea/Editor/Framework',
-       ['TYPO3/CMS/Rtehtmlarea/HTMLArea/Util/TYPO3',
+       ['TYPO3/CMS/Rtehtmlarea/HTMLArea/Util/Util',
+       'TYPO3/CMS/Rtehtmlarea/HTMLArea/Util/Resizable',
+       'TYPO3/CMS/Rtehtmlarea/HTMLArea/DOM/DOM',
+       'TYPO3/CMS/Rtehtmlarea/HTMLArea/Util/TYPO3',
        'TYPO3/CMS/Rtehtmlarea/HTMLArea/Event/Event',
        'TYPO3/CMS/Rtehtmlarea/HTMLArea/Editor/Toolbar',
        'TYPO3/CMS/Rtehtmlarea/HTMLArea/Editor/Iframe',
        'TYPO3/CMS/Rtehtmlarea/HTMLArea/Editor/StatusBar'],
-       function (Typo3, Event, Toolbar, Iframe, Statusbar) {
+       function (Util, Resizable, Dom, Typo3, Event, Toolbar, Iframe, Statusbar) {
 
-       var Framework = Ext.extend(Ext.Container, {
+       /**
+        * Framework constructor
+        */
+       var Framework = function (config) {
+               Util.apply(this, config);
+               // Set some references
+               for (var i = 0, n = this.items.length; i < n; i++) {
+                       var item = this.items[i];
+                       item.framework = this;
+                       this[item.itemId] = item;
+               }
+               // Monitor iframe becoming ready
+               var self = this;
+               Event.one(this.iframe, 'HTMLAreaEventIframeReady', function (event) { Event.stopEvent(event); self.onIframeReady(); return false; });
+               // Let the framefork render itself, but it will fail to do so if inside a hidden tab or inline element
+               if (!this.isNested || Typo3.allElementsAreDisplayed(this.nestedParentElements.sorted)) {
+                       this.render(this.textArea.parentNode, this.textArea.id);
+               } 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
+                       Typo3.accessParentElements(parentElements, 'args[0].render(args[0].textArea.parentNode, args[0].textArea.id)', [this]);
+               }
+       };
+
+       Framework.prototype = {
 
                /**
-                * Constructor
+                * Render the framework
+                *
+                * @param object container: the container into which to insert the framework
+                * @param string position: the id of the child element of the container before which the framework should be inserted
+                * @return void
                 */
-               initComponent: function () {
-                       this.superClass = Framework.superclass;
-                       this.superClass.initComponent.call(this);
-                       // Set some references
-                       this.toolbar = this.getComponent('toolbar');
-                       this.statusBar = this.getComponent('statusBar');
-                       this.iframe = this.getComponent('iframe');
-                       this.textAreaContainer = this.getComponent('textAreaContainer');
-                       this.addListener({
-                               beforedestroy: {
-                                       fn: this.onBeforeDestroy,
-                                       single: true
-                               }
-                       });
-                       // Monitor iframe becoming ready
-                       var self = this;
-                       Event.one(this.iframe, 'HTMLAreaEventIframeReady', function (event) { Event.stopEvent(event); self.onIframeReady(); return false; });
-                       // Let the framefork render itself, but it will fail to do so if inside a hidden tab or inline element
-                       if (!this.isNested || Typo3.allElementsAreDisplayed(this.nestedParentElements.sorted)) {
-                               this.render(this.textArea.parentNode, this.textArea.id);
-                       } 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
-                               Typo3.accessParentElements(parentElements, 'args[0].render(args[0].textArea.parentNode, args[0].textArea.id)', [this]);
+               render: function (container, position) {
+                       this.el = document.createElement('div');
+                       if (this.id) {
+                               this.el.setAttribute('id', this.id);
+                       }
+                       if (this.cls) {
+                               this.el.setAttribute('class', this.cls);
                        }
+                       var position = document.getElementById(position);
+                       this.el = container.insertBefore(this.el, position);
+                       for (var i = 0, n = this.items.length; i < n; i++) {
+                               var item = this.items[i];
+                               item.render(this.el);
+                       }
+                       this.rendered = true;
+               },
+
+               /**
+                * Get the element to which the framework is rendered
+                */
+               getEl: function () {
+                       return this.el;
                },
 
                /**
@@ -62,9 +90,9 @@ define('TYPO3/CMS/Rtehtmlarea/HTMLArea/Editor/Framework',
                        // 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);
+                       Event.on(this.textAreaContainer, 'HTMLAreaEventTextAreaContainerShow', function(event) { Event.stopEvent(event); self.resizable ? self.onTextAreaShow() : self.onWindowResize(); return false; });
                        // 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);
+                       Event.on(this.iframe, 'HTMLAreaEventIframeShow', function(event) { Event.stopEvent(event); self.resizable ? self.onIframeShow() : self.onWindowResize(); return false; });
                        // Monitor window resizing
                        Event.on(window, 'resize', function (event) { self.onWindowResize(); });
                        // If the textarea is inside a form, on reset, re-initialize the HTMLArea content and update the toolbar
@@ -78,11 +106,8 @@ define('TYPO3/CMS/Rtehtmlarea/HTMLArea/Editor/Framework',
                                }
                                Event.on(form, 'reset', function (event) { return self.onReset(event); });
                        }
-                       this.addListener({
-                               resize: {
-                                       fn: this.onFrameworkResize
-                               }
-                       });
+                       // Monitor the framework being resized
+                       Event.on(this, 'HTMLAreaEventFrameworkResize', function (event) { Event.stopEvent(event); self.onFrameworkResize(); return false; });
                },
 
                /**
@@ -143,31 +168,31 @@ define('TYPO3/CMS/Rtehtmlarea/HTMLArea/Editor/Framework',
                },
 
                /**
-                * doLayout will fail if inside a hidden tab or inline element
+                * Get the toolbar
                 */
-               doLayout: function () {
-                       if (!this.isNested || Typo3.allElementsAreDisplayed(this.nestedParentElements.sorted)) {
-                               Framework.superclass.doLayout.call(this);
-                       } 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
-                               Typo3.accessParentElements(parentElements, 'args[0].superClass.doLayout.call(args[0])', [this]);
-                       }
+               getToolbar: function () {
+                       return this.toolbar;
                },
 
                /**
-                * onLayout will fail if inside a hidden tab or inline element
+                * Get the iframe
                 */
-               onLayout: function () {
-                       if (!this.isNested || Typo3.allElementsAreDisplayed(this.nestedParentElements.sorted)) {
-                               Framework.superclass.onLayout.call(this);
-                       } 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
-                               Typo3.accessParentElements(parentElements, 'args[0].superClass.onLayout.call(args[0])', [this]);
-                       }
+               getIframe: function () {
+                       return this.iframe;
+               },
+
+               /**
+                * Get the textarea container
+                */
+               getTextAreaContainer: function () {
+                       return this.textAreaContainer;
+               },
+
+               /**
+                * Get the status bar
+                */
+               getStatusBar: function () {
+                       return this.statusBar;
                },
 
                /**
@@ -175,26 +200,23 @@ define('TYPO3/CMS/Rtehtmlarea/HTMLArea/Editor/Framework',
                 */
                makeResizable: function () {
                        if (this.resizable) {
-                               this.addClass('resizable');
-                               this.resizer = new Ext.Resizable(this.getEl(), {
+                               var self = this;
+                               Dom.addClass(this.getEl(), 'resizable');
+                               this.resizer = Resizable.makeResizable(this.getEl(), {
+                                       minHeight: 200,
                                        minWidth: 300,
                                        maxHeight: this.maxHeight,
-                                       dynamic: false
+                                       stop: function (event, ui) { Event.stopEvent(event); self.onHtmlAreaResize(ui.size); return 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.style.width = (this.getInnerWidth()-9) + 'px';
-                       this.textArea.style.height = this.getInnerHeight() + 'px';
+               onHtmlAreaResize: function (size) {
+                       Dom.setSize(this.getEl(), size);
+                       this.onFrameworkResize();
                },
 
                /**
@@ -235,32 +257,26 @@ define('TYPO3/CMS/Rtehtmlarea/HTMLArea/Editor/Framework',
                        } else {
                                // Width is specified in %
                                // Framework sizing on actual window resize
-                               var frameworkWidth = parseInt(((Typo3.getWindowSize().width - this.textAreaInitialSize.wizardsWidth - (this.fullScreen ? 10 : Ext.getScrollBarWidth()) - this.getBox().x - 15) * parseInt(this.textAreaInitialSize.width))/100);
-                       }
-                       if (this.resizable) {
-                               this.resizer.resizeTo(frameworkWidth, frameworkHeight);
-                       } else {
-                               this.setSize(frameworkWidth, frameworkHeight);
-                               this.doLayout();
+                               var frameworkWidth = parseInt(((Typo3.getWindowSize().width - this.textAreaInitialSize.wizardsWidth - (this.fullScreen ? 10 : Util.getScrollBarWidth()) - Dom.getPosition(this.getEl()).x - 15) * parseInt(this.textAreaInitialSize.width))/100);
                        }
+                       Dom.setSize(this.getEl(), { width: frameworkWidth, height: frameworkHeight});
+                       Event.trigger(this, 'HTMLAreaEventFrameworkResize');
                },
 
                /**
                 * Resize the framework components
                 */
                onFrameworkResize: function () {
-                       this.iframe.getEl().dom.style.width = (this.getInnerWidth()-9) + 'px';
-                       this.iframe.setHeight(this.getInnerHeight());
-                       this.textArea.style.width = (this.getInnerWidth()-9) + 'px';
-                       this.textArea.style.height = this.getInnerHeight() + 'px';
+                       Dom.setSize(this.iframe.getEl().dom, { width: this.getInnerWidth(), height: this.getInnerHeight()});
+                       Dom.setSize(this.textArea, { width: this.getInnerWidth(), height: 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.style.height = this.getInnerHeight() + 'px';
+                       Dom.setSize(this.iframe.getEl().dom, { height: this.getInnerHeight()});
+                       Dom.setSize(this.textArea, { width: this.getInnerWidth(), height: this.getInnerHeight()});
                },
 
                /**
@@ -270,8 +286,9 @@ define('TYPO3/CMS/Rtehtmlarea/HTMLArea/Editor/Framework',
                        if (this.getInnerHeight() <= 0) {
                                this.onWindowResize();
                        } else {
-                               this.iframe.setHeight(this.getInnerHeight());
-                               this.textArea.style.height = this.getInnerHeight() + 'px';
+                               //this.iframe.setHeight(this.getInnerHeight());
+                               Dom.setSize(this.iframe.getEl().dom, { height: this.getInnerHeight()});
+                               Dom.setSize(this.textArea, { height: this.getInnerHeight()});
                        }
                },
 
@@ -279,14 +296,14 @@ define('TYPO3/CMS/Rtehtmlarea/HTMLArea/Editor/Framework',
                 * Calculate the height available for the editing iframe
                 */
                getInnerHeight: function () {
-                       return this.getSize().height - this.toolbar.getHeight() - this.statusBar.getHeight() - 5;
+                       return Dom.getSize(this.getEl()).height - this.toolbar.getHeight() - this.statusBar.getHeight() - 5;
                },
 
                /**
                 * Calculate the width available for the editing iframe
                 */
                getInnerWidth: function () {
-                       return this.getSize().width;
+                       return Dom.getSize(this.getEl()).width;
                },
 
                /**
@@ -335,25 +352,28 @@ define('TYPO3/CMS/Rtehtmlarea/HTMLArea/Editor/Framework',
                /**
                 * Cleanup on framework destruction
                 */
-               onBeforeDestroy: function () {
+               destroy: function () {
                        Event.off(window);
+                       Event.off(this.textAreaContainer);
                        // Cleaning references to DOM in order to avoid IE memory leaks
                        var form = this.textArea.form;
                        if (form) {
                                Event.off(form);
                                form.htmlAreaPreviousOnReset = null;
                        }
-                       Ext.getBody().dom = null;
                        // ExtJS is not releasing any resources when the iframe is unloaded
                        this.toolbar.destroy();
                        this.statusBar.destroy();
-                       this.removeAll(true);
+                       while (this.el.firstChild) {
+                               this.el.removeChild(this.el.firstChild);
+                       }
                        if (this.resizer) {
-                               this.resizer.destroy();
+                               Resizable.destroy(this.resizer);
                        }
+                       this.el = null;
                        return true;
                }
-       });
+       };
 
        return Framework;
 
index 6dccbb1..50f583c 100644 (file)
@@ -34,6 +34,11 @@ define('TYPO3/CMS/Rtehtmlarea/HTMLArea/Editor/Iframe',
                                        fn: this.initEventListeners,
                                        single: true
                                },
+                               show: {
+                                       fn: function (iframe) {
+                                               Event.trigger(iframe, 'HTMLAreaEventIframeShow');
+                                       }
+                               },
                                beforedestroy: {
                                        fn: this.onBeforeDestroy,
                                        single: true
@@ -109,14 +114,14 @@ define('TYPO3/CMS/Rtehtmlarea/HTMLArea/Editor/Iframe',
                 * Get a reference to the toolbar
                 */
                getToolbar: function () {
-                       return this.ownerCt.toolbar;
+                       return this.framework.toolbar;
                },
 
                /**
                 * Get a reference to the statusBar
                 */
                getStatusBar: function () {
-                       return this.ownerCt.statusBar;
+                       return this.framework.statusBar;
                },
 
                /**
@@ -365,7 +370,7 @@ define('TYPO3/CMS/Rtehtmlarea/HTMLArea/Editor/Iframe',
                                                        }
                                                        self.fireEvent('show');
                                                } else {
-                                                       self.ownerCt.textAreaContainer.fireEvent('show');
+                                                       self.framework.textAreaContainer.fireEvent('show');
                                                }
                                                self.getToolbar().update();
                                        }
index 4b96767..239a80a 100644 (file)
@@ -51,11 +51,11 @@ define('TYPO3/CMS/Rtehtmlarea/HTMLArea/Editor/StatusBar',
                        var self = this;
                        // Monitor toolbar updates in order to refresh the contents of the statusbar
                        // The toolbar must have been rendered
-                       Event.on(this.ownerCt.toolbar, 'HTMLAreaEventToolbarUpdate', function (event, mode, selectionEmpty, ancestors, endPointsInSameBlock) { Event.stopEvent(event); self.onUpdateToolbar(mode, selectionEmpty, ancestors, endPointsInSameBlock); return false; });
+                       Event.on(this.framework.toolbar, 'HTMLAreaEventToolbarUpdate', function (event, mode, selectionEmpty, ancestors, endPointsInSameBlock) { Event.stopEvent(event); self.onUpdateToolbar(mode, selectionEmpty, ancestors, endPointsInSameBlock); return false; });
                        // Monitor editor changing mode
                        Event.on(this.getEditor(), 'HTMLAreaEventModeChange', function (event, mode) { Event.stopEvent(event); self.onModeChange(mode); return false; });
                        // Monitor word count change
-                       Event.on(this.ownerCt.iframe, 'HTMLAreaEventWordCountChange', function (event, delay) { Event.stopEvent(event); self.onWordCountChange(delay); return false; });
+                       Event.on(this.framework.iframe, 'HTMLAreaEventWordCountChange', function (event, delay) { Event.stopEvent(event); self.onWordCountChange(delay); return false; });
                },
 
                /**
diff --git a/typo3/sysext/rtehtmlarea/Resources/Public/JavaScript/HTMLArea/Util/Resizable.js b/typo3/sysext/rtehtmlarea/Resources/Public/JavaScript/HTMLArea/Util/Resizable.js
new file mode 100644 (file)
index 0000000..5fe02aa
--- /dev/null
@@ -0,0 +1,50 @@
+/**
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+/***************************************************
+ *  Make resizable
+ ***************************************************/
+define('TYPO3/CMS/Rtehtmlarea/HTMLArea/Util/Resizable',
+       ['jquery',
+       'jquery-ui/resizable'],
+       function ($, Resizable) {
+
+       var Resizable = {
+
+               /**
+                * Make an element resizable
+                *
+                * @param object element: the target element
+                * @param object
+                */
+               makeResizable: function (element, config) {
+                       if (typeof config !== 'undefined') {
+                               return $(element).resizable(config);
+                       } else {
+                               return $(element).resizable();
+                       }
+               },
+
+               /**
+                * Removes the resizable feature from the element
+                *
+                * @param object element: the target element
+                * @return object the element
+                */
+               destroy: function (element) {
+                       return $(element).resizable('destroy');
+               }
+       };
+
+       return Resizable;
+
+});
index ff13339..764e82c 100644 (file)
@@ -13,7 +13,9 @@
 /***************************************************
  *  UTILITY FUNCTIONS
  ***************************************************/
-define('TYPO3/CMS/Rtehtmlarea/HTMLArea/Util/Util', [], function() {
+define('TYPO3/CMS/Rtehtmlarea/HTMLArea/Util/Util',
+       ['TYPO3/CMS/Rtehtmlarea/HTMLArea/UserAgent/UserAgent'],
+       function (UserAgent) {
 
        var Util = {
 
@@ -101,6 +103,36 @@ define('TYPO3/CMS/Rtehtmlarea/HTMLArea/Util/Util', [], function() {
                        subClass.prototype.constructor = subClass;
                        subClass.super = superClass;
                        return subClass;
+               },
+
+               /**
+                * Width of the browser scrollbar
+                */
+               scrollBarWidth: null,
+
+               /**
+                * Utility method for getting the width of the browser scrollbar. This can differ depending on
+                * operating system settings, such as the theme or font size.
+                *
+                * @return integer The width of the scrollbar.
+                */
+               getScrollBarWidth: function (){
+                       if (Util.scrollBarWidth === null) {
+                               // Append a div, do calculation and then remove it
+                               var div = document.createElement('div');
+                               div.style.cssText = 'position:absolute!important;left:-10000px;top:-10000px;visibility:hidden;width:100px;height:50px;overflow:hidden;';
+                               div = document.body.appendChild(div);
+                               var innerDiv = document.createElement('div');
+                               innerDiv.style.height = '200px';
+                               innerDiv = div.appendChild(innerDiv);
+                               var w1 = innerDiv.offsetWidth;
+                               div.style.overflow = (UserAgent.isWebKit || UserAgent.isGecko) ? 'auto' : 'scroll';
+                               var w2 = innerDiv.offsetWidth;
+                               div.parentNode.removeChild(div);
+                               // Need to add 2 to ensure we leave enough space
+                               Util.scrollBarWidth = w1 - w2 + 2;
+                   }
+                   return Util.scrollBarWidth;
                }
        };