Revert "[TASK] Migrate to ExtJS 4: Migrate TCEforms"
authorOliver Hader <oliver@typo3.org>
Fri, 13 Jan 2012 10:55:47 +0000 (11:55 +0100)
committerOliver Hader <oliver@typo3.org>
Fri, 13 Jan 2012 11:14:36 +0000 (12:14 +0100)
This reverts commit 1a1930c8214218a4e739baaf5ca9248126cacaed.

Change-Id: I5382dd50da464ce85db6eb09d7161e56d35266bd
Resolves: #33164
Releases: 4.7
Reviewed-on: http://review.typo3.org/7772
Reviewed-by: Oliver Hader
Tested-by: Oliver Hader
12 files changed:
t3lib/class.t3lib_tceforms.php
t3lib/js/extjs/components/slider/ValueSlider.js
t3lib/js/extjs/ux/Ext.app.SearchField.js
t3lib/js/extjs/ux/Ext.grid.RowExpander.js
t3lib/js/extjs/ux/Ext.ux.DateTimePicker.js
t3lib/js/extjs/ux/Ext.ux.elasticTextArea.js [deleted file]
t3lib/js/extjs/ux/ext.resizable.js [new file with mode: 0644]
t3lib/js/extjs/ux/ext.ux.tabclosemenu.js
t3lib/js/extjs/ux/flashmessages.js
t3lib/js/extjs/ux/resize.css [new file with mode: 0644]
t3lib/js/extjs/ux/resize.gif [new file with mode: 0644]
typo3/sysext/t3skin/stylesheets/structure/element_datetime_picker.css [deleted file]

index adb217c..e60c5c5 100644 (file)
@@ -5302,7 +5302,7 @@ class t3lib_TCEforms {
                                // make textareas resizable and flexible
                        if (!($GLOBALS['BE_USER']->uc['resizeTextareas'] == '0' && $GLOBALS['BE_USER']->uc['resizeTextareas_Flexible'] == '0')) {
                                $pageRenderer->addCssFile($this->backPath . '../t3lib/js/extjs/ux/resize.css');
-                               $this->loadJavascriptLib('../t3lib/js/extjs/ux/Ext.ux.elasticTextArea.js');
+                               $this->loadJavascriptLib('../t3lib/js/extjs/ux/ext.resizable.js');
                        }
                        $resizableSettings = array(
                                'textareaMaxHeight' => $GLOBALS['BE_USER']->uc['resizeTextareas_MaxHeight'] > 0 ? $GLOBALS['BE_USER']->uc['resizeTextareas_MaxHeight'] : '600',
index a490997..46d466b 100644 (file)
  *
  *  This copyright notice MUST APPEAR in all copies of the script!
  ***************************************************************/
-Ext.define('TYPO3.Components.TcaValueSlider', {
-       extend: 'Ext.slider.Single',
 
+Ext.ns('TYPO3.Components');
+
+TYPO3.Components.TcaValueSlider = Ext.extend(Ext.slider.SingleSlider, {
        itemName: null,
        getField: null,
        changeCallback: null,
@@ -49,7 +50,7 @@ Ext.define('TYPO3.Components.TcaValueSlider', {
                        keyIncrement: step,
                        increment: step,
                        type: this.type,
-                       plugins: Ext.create('Ext.slider.Tip', {
+                       plugins: new Ext.slider.Tip({
                                getText: function(thumb) {
                                        return thumb.slider.renderValue(thumb.value);
                                }
@@ -140,4 +141,6 @@ Ext.define('TYPO3.Components.TcaValueSlider', {
                return hours + ':' + minutes;
        }
 
-});
\ No newline at end of file
+});
+
+Ext.reg('TYPO3.Components.TcaValueSlider', TYPO3.Components.TcaValueSlider);
\ No newline at end of file
index bd710dc..03784b2 100644 (file)
@@ -5,10 +5,9 @@
  *
  * http://extjs.com/license
  */
-Ext.define('Ext.app.SearchField', {
-       extend: 'Ext.form.TwinTriggerField',
 
-       initComponent: function() {
+Ext.app.SearchField = Ext.extend(Ext.form.TwinTriggerField, {
+       initComponent : function() {
                Ext.app.SearchField.superclass.initComponent.call(this);
                this.on('specialkey', function(f, e) {
                        if (e.getKey() == e.ENTER) {
index 0917d7b..ebbf2a6 100644 (file)
  * including getter and setter functions, and minor mods
  * to the beforeExpand and expandRow functions
  */
-Ext.define('Ext.grid.RowExpander', {
-       extend: 'Ext.util.Observable',
 
+Ext.grid.RowExpander = function(config) {
+       Ext.apply(this, config);
+       Ext.grid.RowExpander.superclass.constructor.call(this);
+
+       if (this.tpl) {
+               if (typeof this.tpl == 'string') {
+                       this.tpl = new Ext.Template(this.tpl);
+               }
+               this.tpl.compile();
+       }
+
+       this.state = {};
+       this.bodyContent = {};
+
+       this.addEvents({
+               beforeexpand : true,
+               expand: true,
+               beforecollapse: true,
+               collapse: true
+       });
+};
+
+Ext.extend(Ext.grid.RowExpander, Ext.util.Observable, {
        header: "",
        width: 20,
        sortable: false,
        fixed:true,
        dataIndex: '',
        id: 'expander',
-       lazyRender: true,
+       lazyRender : true,
        enableCaching: true,
 
-       constructor: function(config) {
-               Ext.apply(this, config);
-               Ext.grid.RowExpander.superclass.constructor.call(this);
-
-               if (this.tpl) {
-                       if (typeof this.tpl == 'string') {
-                               this.tpl = Ext.create('Ext.Template', this.tpl);
-                       }
-                       this.tpl.compile();
-               }
-
-               this.state = {};
-               this.bodyContent = {};
-
-               this.addEvents({
-                       beforeexpand : true,
-                       expand: true,
-                       beforecollapse: true,
-                       collapse: true
-               });
-       },
-
        getRowClass : function(record, rowIndex, p, ds) {
                p.cols = p.cols-1;
                var content = this.bodyContent[record.id];
@@ -60,7 +59,7 @@ Ext.define('Ext.grid.RowExpander', {
                this.grid = grid;
 
                var view = grid.getView();
-               view.getRowClass = Ext.Function.bind(this.getRowClass, this);
+               view.getRowClass = this.getRowClass.createDelegate(this);
 
                view.enableRowBody = true;
 
@@ -141,7 +140,7 @@ Ext.define('Ext.grid.RowExpander', {
                        // If remoteDataMethod is defined then we'll need a div, with a unique ID,
                        //  to place the content
                        if (this.remoteDataMethod) {
-                               this.tpl = Ext.create('Ext.Template', "<div id=\"remData" + rowIndex + "\" class=\"rem-data-expand\"><\div>");
+                               this.tpl = new Ext.Template("<div id=\"remData" + rowIndex + "\" class=\"rem-data-expand\"><\div>");
                        }
                        if (this.tpl && this.lazyRender) {
                                body.innerHTML = this.getBodyContent(record, rowIndex);
index 591bdaa..999ccc0 100644 (file)
@@ -1,65 +1,15 @@
-Ext.define('Ext.ux.DateTimePicker', {
-       extend: 'Ext.picker.Date',
-       alias:['widget.datetimepicker'],
+Ext.ns('Ext.ux', 'Ext.ux.menu', 'Ext.ux.form');
+
+Ext.ux.DateTimePicker = Ext.extend(Ext.DatePicker, {
 
        timeFormat: 'H:i',
-       showToday: true,
-       ariaTitle: '',
-       cls: 'typo3-datetime-picker',
-       /**
-        * ExtJS 4.0.7
-        * Remove title that overlays qtips
-        */
-       renderTpl: [
-               '<div class="{cls}" id="{id}" role="grid">',
-                   '<div role="presentation" class="{baseCls}-header">',
-                       '<div class="{baseCls}-prev"><a id="{id}-prevEl" href="#" role="button" title="{prevText}"></a></div>',
-                       '<div class="{baseCls}-month" id="{id}-middleBtnEl"></div>',
-                       '<div class="{baseCls}-next"><a id="{id}-nextEl" href="#" role="button" title="{nextText}"></a></div>',
-                   '</div>',
-                   '<table id="{id}-eventEl" class="{baseCls}-inner" cellspacing="0" role="presentation" title="{ariaTitle} {value:this.longDay}">',
-                       '<thead role="presentation"><tr role="presentation">',
-                           '<tpl for="dayNames">',
-                               '<th role="columnheader" title="{.}"><span>{.:this.firstInitial}</span></th>',
-                           '</tpl>',
-                       '</tr></thead>',
-                       '<tbody role="presentation"><tr role="presentation">',
-                           '<tpl for="days">',
-                               '{#:this.isEndOfWeek}',
-                               '<td role="gridcell" id="{[Ext.id()]}">',
-                                   '<a role="presentation" href="#" hidefocus="on" class="{parent.baseCls}-date" tabIndex="1">',
-                                       '<em role="presentation"><span role="presentation"></span></em>',
-                                   '</a>',
-                               '</td>',
-                           '</tpl>',
-                       '</tr></tbody>',
-                   '</table>',
-                   '<tpl if="showToday">',
-                       '<div id="{id}-footerEl" role="presentation" class="{baseCls}-footer"></div>',
-                   '</tpl>',
-               '</div>',
-               {
-                   firstInitial: function(value) {
-                       return value.substr(0,1);
-                   },
-                   isEndOfWeek: function(value) {
-                       // convert from 1 based index to 0 based
-                       // by decrementing value once.
-                       value--;
-                       var end = value % 7 === 0 && value !== 0;
-                       return end ? '</tr><tr role="row">' : '';
-                   },
-                   longDay: function(value){
-                       return Ext.Date.format(value, this.longDayFormat);
-                   }
-               }
-       ],
 
        initComponent: function() {
                var t = this.timeFormat.split(':');
                this.hourFormat = t[0];
                this.minuteFormat = t[1];
-               this.callParent(arguments);
+
+               Ext.ux.DateTimePicker.superclass.initComponent.call(this);
        },
 
        /**
@@ -93,12 +43,12 @@ Ext.define('Ext.ux.DateTimePicker', {
         */
        setValue: function(value) {
                var old = this.value;
-               this.value = Ext.Date.clearTime(value,true);
+               this.value = value.clearTime(true);
                if (this.el) {
                        this.update(this.value);
                }
-               this.hourField.setValue(Ext.Date.format(value, this.hourFormat));
-               this.minuteField.setValue(Ext.Date.format(value, this.minuteFormat));
+               this.hourField.setValue(value.format(this.hourFormat));
+               this.minuteField.setValue(value.format(this.minuteFormat));
        },
 
        /**
@@ -106,8 +56,8 @@ Ext.define('Ext.ux.DateTimePicker', {
         * @param {Date} value The date to set
         */
        setTime: function(value) {
-               this.hourField.setValue(Ext.Date.format(value, this.hourFormat));
-               this.minuteField.setValue(Ext.Date.format(value, this.minuteFormat));
+               this.hourField.setValue(value.format(this.hourFormat));
+               this.minuteField.setValue(value.format(this.minuteFormat));
        },
 
        /**
@@ -115,62 +65,192 @@ Ext.define('Ext.ux.DateTimePicker', {
         * @param {Date} value The date to which time should be added
         */
        addTimeToValue: function(date) {
-               var localDate = Ext.Date.clearTime(date);
-               return Ext.Date.add(Ext.Date.add(localDate, Ext.Date.HOUR, this.hourField.inputEl.getValue()), Ext.Date.MINUTE, this.minuteField.inputEl.getValue());
+               return date.clearTime().add(Date.HOUR, this.hourField.getValue()).add(Date.MINUTE, this.minuteField.getValue());
        },
 
-       onRender: function (container, position) {
-               var me = this,
-                       days = new Array(me.numDays),
-                       today = Ext.Date.format(new Date(), me.format);
+       onRender: function(container, position) {
+               var m = [
+                       '<table cellspacing="0">',
+                       '<tr><td class="x-date-left"><a href="#" title="',
+                       this.prevText ,
+                       '">&#160;</a></td><td class="x-date-middle" align="center"></td><td class="x-date-right"><a href="#" title="',
+                       this.nextText ,
+                       '">&#160;</a></td></tr>',
+                       '<tr><td colspan="3"><table class="x-date-inner" cellspacing="0"><thead><tr>'
+               ];
+               var dn = this.dayNames;
+               for (var i = 0; i < 7; i++) {
+                       var d = this.startDay + i;
+                       if (d > 6) {
+                               d = d - 7;
+                       }
+                       m.push('<th><span>', dn[d].substr(0, 1), '</span></th>');
+               }
+               m[m.length] = "</tr></thead><tbody><tr>";
+               for (var i = 0; i < 42; i++) {
+                       if (i % 7 == 0 && i != 0) {
+                               m[m.length] = "</tr><tr>";
+                       }
+                       m[m.length] = '<td><a href="#" hidefocus="on" class="x-date-date" tabIndex="1"><em><span></span></em></a></td>';
+               }
+               m.push('</tr></tbody></table></td></tr>',
+                       this.showToday ? '<tr><td colspan="3" class="x-date-bottom" align="center"></td></tr>' : '',
+                       '</table><div class="x-date-mp"></div>'
+               );
+
+               var el = document.createElement("div");
+               el.className = "x-date-picker";
+               el.innerHTML = m.join("");
 
-               me.callParent(arguments);
-                       // Destroying today button created by the parent class
-               me.todayBtn.destroy();
+               container.dom.insertBefore(el, position);
 
-               me.formPanel = Ext.create('Ext.form.Panel', {
-                       cls: 'typo3-datetime-picker-footer',
-                       layout: 'column',
-                       renderTo: me.footerEl,
-                       defaults: {
-                               labelAlign: 'left',
-                               labelSeparator: ''
+               this.el = Ext.get(el);
+               this.eventEl = Ext.get(el.firstChild);
+
+               new Ext.util.ClickRepeater(this.el.child("td.x-date-left a"), {
+                       handler: this.showPrevMonth,
+                       scope: this,
+                       preventDefault:true,
+                       stopDefault:true
+               });
+
+               new Ext.util.ClickRepeater(this.el.child("td.x-date-right a"), {
+                       handler: this.showNextMonth,
+                       scope: this,
+                       preventDefault:true,
+                       stopDefault:true
+               });
+
+               this.mon(this.eventEl, "mousewheel", this.handleMouseWheel, this);
+
+               this.monthPicker = this.el.down('div.x-date-mp');
+               this.monthPicker.enableDisplayMode('block');
+
+               var kn = new Ext.KeyNav(this.eventEl, {
+                       "left": function(e) {
+                               e.ctrlKey ?
+                                       this.showPrevMonth() :
+                                       this.update(this.activeDate.add("d", -1));
+                       },
+
+                       "right": function(e) {
+                               e.ctrlKey ?
+                                       this.showNextMonth() :
+                                       this.update(this.activeDate.add("d", 1));
+                       },
+
+                       "up": function(e) {
+                               e.ctrlKey ?
+                                       this.showNextYear() :
+                                       this.update(this.activeDate.add("d", -7));
+                       },
+
+                       "down": function(e) {
+                               e.ctrlKey ?
+                                       this.showPrevYear() :
+                                       this.update(this.activeDate.add("d", 7));
                        },
-                       items: [{
+
+                       "pageUp": function(e) {
+                               this.showNextMonth();
+                       },
+
+                       "pageDown": function(e) {
+                               this.showPrevMonth();
+                       },
+
+                       "enter": function(e) {
+                               e.stopPropagation();
+                               this.fireEvent("select", this, this.value);
+                               return true;
+                       },
+
+                       scope : this
+               });
+
+               this.mon(this.eventEl, "click", this.handleDateClick, this, {delegate: "a.x-date-date"});
+
+               this.el.select("table.x-date-inner").unselectable();
+               this.cells = this.el.select("table.x-date-inner tbody td");
+               this.textNodes = this.el.query("table.x-date-inner tbody span");
+
+               this.mbtn = new Ext.Button({
+                       text: "&#160;",
+                       tooltip: this.monthYearText,
+                       renderTo: this.el.child("td.x-date-middle", true)
+               });
+
+               this.mon(this.mbtn, 'click', this.showMonthPicker, this);
+               this.mbtn.el.child('em').addClass("x-btn-arrow");
+
+               if (this.showToday) {
+                       this.todayKeyListener = this.eventEl.addKeyListener(Ext.EventObject.SPACE, this.selectToday, this);
+                       var today = (new Date()).dateFormat(this.format);
+                       this.todayBtn = new Ext.Button({
+                               text: String.format(this.todayText, today),
+                               tooltip: String.format(this.todayTip, today),
+                               handler: this.selectToday,
+                               scope: this
+                       });
+               }
+
+               this.formPanel = new Ext.form.FormPanel({
+                       layout: 'column',
+                       renderTo: this.el.child("td.x-date-bottom", true),
+                       baseCls: 'x-plain',
+                       hideBorders: true,
+                       labelAlign: 'left',
+                       labelWidth: 10,
+                       forceLayout: true,
+                       items: [
+                               {
+                                       columnWidth: .4,
+                                       layout: 'form',
+                                       baseCls: 'x-plain',
+                                       items: [
+                                               {
+                                                       xtype: 'textfield',
+                                                       id: this.getId() + '_hour',
+                                                       maxLength: 2,
+                                                       fieldLabel: '',
+                                                       labelWidth: 30,
+                                                       width: 30,
+                                                       minValue: 0,
+                                                       maxValue: 24,
+                                                       allowBlank: false,
+                                                       labelSeparator: '',
+                                                       tabIndex: 1,
+                                                       maskRe: /[0-9]/
+                                               }
+                                       ]
+                               },
+                               {
                                        columnWidth: .3,
-                                       xtype: 'textfield',
-                                       cls: 'typo3-datetime-picker-hour',
-                                       id: this.getId() + '_hour',
-                                       maxLength: 2,
-                                       fieldLabel: ' ',
-                                       labelWidth: 16,
-                                       width: 20,
-                                       minValue: 0,
-                                       maxValue: 24,
-                                       allowBlank: false,
-                                       tabIndex: 1,
-                                       maskRe: /[0-9]/
-                               },{
+                                       layout: 'form',
+                                       baseCls: 'x-plain',
+                                       items: [
+                                               {
+                                                       xtype: 'textfield',
+                                                       id:     this.getId() + '_minute',
+                                                       maxLength: 2,
+                                                       fieldLabel: ':',
+                                                       labelWidth: 10,
+                                                       width: 30,
+                                                       minValue: 0,
+                                                       maxValue: 59,
+                                                       allowBlank: false,
+                                                       labelSeparator: '',
+                                                       tabIndex: 2,
+                                                       maskRe: /[0-9]/
+                                               }
+                                       ]
+                               },
+                               {
                                        columnWidth: .3,
-                                       xtype: 'textfield',
-                                       cls: 'typo3-datetime-picker-minute',
-                                       id: this.getId() + '_minute',
-                                       maxLength: 2,
-                                       fieldLabel: ' :',
-                                       labelWidth: 5,
-                                       width: 20,
-                                       minValue: 0,
-                                       maxValue: 59,
-                                       allowBlank: false,
-                                       tabIndex: 2,
-                                       maskRe: /[0-9]/
-                               }, Ext.create('Ext.button.Button', {
-                                       columnWidth: .4,
-                                       text: Ext.String.format(me.todayText, today),
-                                       tooltip: Ext.String.format(me.todayTip, today),
-                                       handler: me.selectToday,
-                                       scope: me
-                               })
+                                       layout: 'form',
+                                       baseCls: 'x-plain',
+                                       items: [this.todayBtn]
+                               }
                        ]
                });
 
@@ -196,60 +276,63 @@ Ext.define('Ext.ux.DateTimePicker', {
                if (Ext.isIE) {
                        this.el.repaint();
                }
+               this.update(this.value);
        },
 
-               // private
-       handleDateClick: function (e, t) {
+       // private
+       handleDateClick : function(e, t) {
                e.stopEvent();
-               if (t.dateValue && !Ext.fly(t.parentNode).hasCls("x-date-disabled")) {
+               if (t.dateValue && !Ext.fly(t.parentNode).hasClass("x-date-disabled")) {
                        this.setValue(this.addTimeToValue(new Date(t.dateValue)));
                        this.fireEvent("select", this, this.value);
                }
        },
 
-       selectToday: function() {
+       selectToday : function() {
                if (this.todayBtn && !this.todayBtn.disabled) {
                        this.setValue(new Date());
                        this.fireEvent("select", this, this.value);
                }
        },
 
-       update: function(date, forceRefresh) {
-               this.callParent(arguments);
+       update : function(date, forceRefresh) {
+               Ext.ux.DateTimePicker.superclass.update.call(this, date, forceRefresh);
+
                if (this.showToday) {
                        this.setTime(new Date());
                }
        }
 });
+Ext.reg('datetimepicker', Ext.ux.DateTimePicker);
 
-Ext.define('Ext.ux.menu.DateTimeMenu', {
-       extend: 'Ext.menu.Menu',
-       alias: ['widget.datetimemenu'],
-       floating: true,
-       enableScrolling: false,
-       hideOnClick: true,
+
+Ext.ux.menu.DateTimeMenu = Ext.extend(Ext.menu.Menu, {
+       enableScrolling : false,
+       hideOnClick : true,
        cls: 'x-date-menu x-datetime-menu',
-       initComponent: function () {
+       initComponent : function() {
+
                Ext.apply(this, {
                        plain: true,
                        showSeparator: false,
-                       items: this.picker = Ext.create('Ext.ux.DateTimePicker', Ext.apply({
+                       items: this.picker = new Ext.ux.DateTimePicker(Ext.apply({
                                internalRender: this.strict || !Ext.isIE,
                                ctCls: 'x-menu-datetime-item x-menu-date-item'
                        }, this.initialConfig))
                });
-               this.picker.clearListeners();
+               this.picker.purgeListeners();
 
-               this.callParent(arguments);
+               Ext.ux.menu.DateTimeMenu.superclass.initComponent.call(this);
                this.relayEvents(this.picker, ['select']);
                this.on('select', this.menuHide, this);
                if (this.handler) {
-                       this.on('select', this.handler, this.scope || this);
+                       this.on('select', this.handler, this.scope || this)
                }
        },
        menuHide: function() {
                if (this.hideOnClick) {
-                       this.hide();
+                       this.hide(true);
                }
        }
-});
\ No newline at end of file
+});
+Ext.reg('datetimemenu', Ext.ux.menu.DateTimeMenu);
\ No newline at end of file
diff --git a/t3lib/js/extjs/ux/Ext.ux.elasticTextArea.js b/t3lib/js/extjs/ux/Ext.ux.elasticTextArea.js
deleted file mode 100644 (file)
index ebd6bb3..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/**
-*
-* Ext.ux.elasticTextArea Extension Class for Ext 3.x Library
-*
-* @author  Steffen Kamper
-*
-* @license Ext.ux.elasticTextArea is licensed under the terms of
-* the Open Source LGPL 3.0 license.  Commercial use is permitted to the extent
-* that the code/component(s) do NOT become part of another Open Source or Commercially
-* licensed development library or toolkit without explicit permission.
-*
-* License details: http://www.gnu.org/licenses/lgpl.html
-*
-*/
-Ext.ux.elasticTextArea = function(){
-
-    var defaultConfig = function(){
-        return {
-            minHeight : 0
-            ,maxHeight : 0
-            ,growBy: 12
-        }
-    }
-
-    var processOptions = function(config){
-        var o = defaultConfig();
-        var options = {};
-        Ext.apply(options, config, o);
-
-        return options ;
-    }
-
-    return {
-        div : null
-        ,renderTo: function(elementId, options){
-
-            var el = Ext.get(elementId);
-            var width = el.getWidth();
-            var height = el.getHeight();
-
-            var styles = el.getStyles('padding-top', 'padding-bottom', 'padding-left', 'padding-right', 'line-height', 'font-size', 'font-family', 'font-weight');
-
-            if(! this.div){
-                var options = processOptions(options);
-
-                this.div = Ext.core.DomHelper.append(Ext.getBody() || document.body, {
-                    'id':elementId + '-preview-div'
-                    ,'tag' : 'div'
-                    ,'background': 'red'
-                    ,'style' : 'position: absolute; top: -100000px; left: -100000px;'
-                }, true)
-                Ext.core.DomHelper.applyStyles(this.div, styles);
-
-                el.on('keyup', function() {
-                        this.renderTo(elementId, options);
-                }, this);
-            }
-            this.div.setWidth(parseInt(el.getStyle('width')));
-            //replace \n with <br>&nbsp; so that the enter key can trigger and height increase
-            //but first remove all previous entries, so that the height mesurement can be as accurate as possible
-            this.div.update(
-                    el.dom.value.replace(/<br \/>&nbsp;/, '<br />')
-                                .replace(/<|>/g, ' ')
-                                .replace(/&/g,"&amp;")
-                                .replace(/\n/g, '<br />&nbsp;')
-                    );
-
-                       var growBy = parseInt(el.getStyle('line-height'));
-                       growBy = growBy ? growBy + 1 : 1;
-                       if (growBy === 1) {
-                               growBy = options.growBy;
-                       }
-                       var textHeight = this.div.getHeight();
-                       textHeight = textHeight ? textHeight + growBy : growBy;
-
-            if ( (textHeight > options.maxHeight ) && (options.maxHeight > 0) ){
-                textHeight = options.maxHeight ;
-                el.setStyle('overflow', 'auto');
-            }
-            if ( (textHeight < options.minHeight ) && (options.minHeight > 0) ) {
-                textHeight = options.minHeight ;
-                el.setStyle('overflow', 'auto');
-            }
-
-            el.setHeight(textHeight , true);
-        }
-    }
-}
diff --git a/t3lib/js/extjs/ux/ext.resizable.js b/t3lib/js/extjs/ux/ext.resizable.js
new file mode 100644 (file)
index 0000000..7b76ad5
--- /dev/null
@@ -0,0 +1,1026 @@
+/**
+ *
+ * Ext.ux.EventZone Extension Class for Ext 3.x Library
+ *
+ * @author  Nigel White
+ *
+ * @license Ext.ux.EventZone is licensed under the terms of
+ * the Open Source LGPL 3.0 license.  Commercial use is permitted to the extent
+ * that the code/component(s) do NOT become part of another Open Source or Commercially
+ * licensed development library or toolkit without explicit permission.
+ * 
+ * License details: http://www.gnu.org/licenses/lgpl.html
+ *
+ * @class Ext.ux.EventZone
+ * <p>This class implements a "virtual element" at a relative size and position
+ * <i>within</i> an existing element. It provides mouse events from a zone of an element of
+ * defined dimensions.</p>
+ * <p>The zone is defined using <code>top</code>, <code>right</code>, <code>bottom</code>,
+ * <code>left</code>, <code>width</code> and <code>height</code> options which specify
+ * the bounds of the zone in a similar manner to the CSS style properties of those names.</p>
+ * @cfg {String|HtmlElement} el The element in which to create the zone.
+ * @cfg {Array} points An Array of points within the element defining the event zone.
+ * @cfg {Number} top The top of the zone. If negative means an offset from the bottom.
+ * @cfg {Number} right The right of the zone. If negative means an offset from the right.
+ * @cfg {Number} left The left of the zone. If negative means an offset from the right.
+ * @cfg {Number} bottom The bottom of the zone. If negative means an offset from the bottom.
+ * @cfg {Number} width The width of the zone.
+ * @cfg {Number} height The height of the zone.
+ * @constructor
+ * Create a new EventZone
+ * @param {Object} config The config object.
+ */
+Ext.ux.EventZone = Ext.extend(Ext.util.Observable, {
+
+    constructor: function(config) {
+        this.initialConfig = config;
+        this.addEvents(
+            /**
+             * @event mouseenter
+             * This event fires when the mouse enters the zone.
+             * @param {EventObject} e the underlying mouse event.
+             * @param {EventZone} this
+             */
+            'mouseenter',
+            /**
+             * @event mousedown
+             * This event fires when the mouse button is depressed within the zone.
+             * @param {EventObject} e the underlying mouse event.
+             * @param {EventZone} this
+             */
+            'mousedown',
+            /**
+             * @event mousemove
+             * This event fires when the mouse moves within the zone.
+             * @param {EventObject} e the underlying mouse event.
+             * @param {EventZone} this
+             */
+            'mousemove',
+            /**
+             * @event mouseup
+             * This event fires when the mouse button is released within the zone.
+             * @param {EventObject} e the underlying mouse event.
+             * @param {EventZone} this
+             */
+            'mouseup',
+            /**
+             * @event mouseenter
+             * This event fires when the mouse is clicked within the zone.
+             * @param {EventObject} e the underlying mouse event.
+             * @param {EventZone} this
+             */
+            'click',
+            /**
+             * @event mouseleave
+             * This event fires when the mouse leaves the zone.
+             * @param {EventObject} e the underlying mouse event.
+             * @param {EventZone} this
+             */
+            'mouseleave'
+        );
+        Ext.apply(this, config);
+        this.el = Ext.get(this.el);
+
+//      If a polygon within the element is specified...
+        if (this.points) {
+            this.polygon = new Ext.lib.Polygon(this.points);
+            this.points = this.polygon.points;
+        }
+
+        Ext.ux.EventZone.superclass.constructor.call(this);
+        this.el.on({
+            mouseenter: this.handleMouseEvent,
+            mousedown: this.handleMouseEvent,
+            mousemove: this.handleMouseEvent,
+            mouseup: this.handleMouseEvent,
+            click: this.handleMouseEvent,
+            mouseleave: this.handleMouseEvent,
+            scope: this
+        });
+    },
+
+    handleMouseEvent: function(e) {
+        var r = this.polygon ? this.getPolygon() : this.getRegion();
+        var inBounds = r.contains(e.getPoint());
+
+        switch (e.type) {
+            // mouseenter fires this
+            case 'mouseover':
+               if (inBounds) {
+                   this.mouseIn = true;
+                   this.fireEvent('mouseenter', e, this);
+               }
+               break;
+            // mouseleave fires this
+            case 'mouseout':
+               this.mouseIn = false;
+               this.fireEvent('mouseleave', e, this);
+               break;
+           case 'mousemove':
+               if (inBounds) {
+                   if (this.mouseIn) {
+                       this.fireEvent('mousemove', e, this);
+                   } else {
+                       this.mouseIn = true;
+                       this.fireEvent('mouseenter', e, this);
+                   }
+               } else {
+                   if (this.mouseIn) {
+                       this.mouseIn = false;
+                       this.fireEvent('mouseleave', e, this);
+                   }
+               }
+               break;
+           default:
+               if (inBounds) {
+                   this.fireEvent(e.type, e, this);
+               }
+        }
+    },
+
+    getPolygon: function() {
+        var xy = this.el.getXY();
+        return this.polygon.translate(xy[0], xy[1]);
+    },
+
+    getRegion: function() {
+        var r = this.el.getRegion();
+
+//      Adjust left boundary of region
+        if (Ext.isNumber(this.left)) {
+            if (this.left < 0) {
+                r.left = r.right + this.left;
+            } else {
+                r.left += this.left;
+            }
+        }
+
+//      Adjust right boundary of region
+        if (Ext.isNumber(this.width)) {
+            r.right = r.left + this.width;
+        } else if (Ext.isNumber(this.right)) {
+            r.right = (this.right < 0) ? r.right + this.right : r.left + this.right;
+        }
+
+//      Adjust top boundary of region
+        if (Ext.isNumber(this.top)) {
+            if (this.top < 0) {
+                r.top = r.bottom + this.top;
+            } else {
+                r.top += this.top;
+            }
+        }
+
+//      Adjust bottom boundary of region
+        if (Ext.isNumber(this.height)) {
+            r.bottom = r.top + this.height;
+        } else if (Ext.isNumber(this.bottom)) {
+            r.bottom = (this.bottom < 0) ? r.bottom + this.bottom : r.top + this.bottom;
+        }
+
+        return r;
+    }
+});
+
+/**
+ * @class Ext.lib.Polygon
+ * <p>This class encapsulates an absolute area of the document bounded by a list of points.</p>
+ * @constructor
+ * Create a new Polygon
+ * @param {Object} points An Array of <code>[n,n]</code> point specification Arrays, or
+ * an Array of Ext.lib.Points, or an HtmlElement, or an Ext.lib.Region.
+ */
+Ext.lib.Polygon = Ext.extend(Ext.lib.Region, {
+    constructor: function(points) {
+        var i, l, el;
+        if (l = points.length) {
+            if (points[0].x) {
+                for (i = 0; i < l; i++) {
+                    points[i] = [ points[i].x, points[i].y ];
+                }
+            }
+            this.points = points;
+        } else {
+            if (el = Ext.get(points)) {
+                points = Ext.lib.Region.getRegion(el.dom);
+            }
+            if (points instanceof Ext.lib.Region) {
+                this.points = [
+                    [points.left, points.top],
+                    [points.right, points.top],
+                    [points.right, points.bottom],
+                    [points.left, points.bottom]
+                ];
+            }
+        }
+    },
+
+    /**
+     * Returns a new Polygon translated by the specified <code>X</code> and <code>Y</code> increments.
+     * @param xDelta {Number} The <code>X</code> translation increment.
+     * @param xDelta {Number} The <code>Y</code> translation increment.
+     * @return {Polygon} The resulting Polygon.
+     */
+    translate: function(xDelta, yDelta) {
+        var r = [], p = this.points, l = p.length, i;
+        for (i = 0; i < l; i++) {
+            r[i] = [ p[i][0] + xDelta, p[i][1] + yDelta ];
+        }
+        return new Ext.lib.Polygon(r);
+    },
+
+    /**
+     * Returns the area of this Polygon.
+     */
+    getArea: function() {
+        var p = this.points, l = p.length, area = 0, i, j = 0;
+        for (i = 0; i < l; i++) {
+            j++;
+            if (j == l) {
+                j = 0;
+            }
+            area += (p[i][0] + p[j][0]) * (p[i][1] - p[j][1]);
+        }
+        return area * 0.5;
+    },
+
+    /**
+     * Returns <code>true</code> if this Polygon contains the specified point. Thanks
+     * to http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html for the algorithm.
+     * @param pt {Point|Number} Either an Ext.lib.Point object, or the <code>X</code> coordinate to test.
+     * @param py {Number} <b>Optional.</b> If the first parameter was an <code>X</code> coordinate, this is the <code>Y</code> coordinate.
+     */
+    contains: function(pt, py) {
+        var f = (arguments.length == 1),
+            testX = f ? pt.x : pt,
+            testY = f ? pt.y : py,
+            p = this.points,
+            nvert = p.length,
+            j = nvert - 1,
+            i, j, c = false;
+        for (i = 0; i < nvert; j = i++) {
+            if ( ((p[i][1] > testY) != (p[j][1] > testY)) &&
+             (testX < (p[j][0]-p[i][0]) * (testY-p[i][1]) / (p[j][1]-p[i][1]) + p[i][0])) {
+                c = !c;
+            }
+        }
+        return c;
+    }
+});
+
+/**
+ * @class Ext.Resizable
+ * @extends Ext.util.Observable
+ * This is an override of Ext.Resizable to make usage of the Ex.ux.EventZone
+ * <p>Applies virtual drag handles to an element to make it resizable.</p>
+ * <p>Here is the list of valid resize handles:</p>
+ * <pre>
+Value   Description
+------  -------------------
+ 'n'     north
+ 's'     south
+ 'e'     east
+ 'w'     west
+ 'nw'    northwest
+ 'sw'    southwest
+ 'se'    southeast
+ 'ne'    northeast
+ 'all'   all
+</pre>
+ * <p>Here's an example showing the creation of a typical Resizable:</p>
+ * <pre><code>
+var resizer = new Ext.Resizable('element-id', {
+    handles: 'all',
+    minWidth: 200,
+    minHeight: 100,
+    maxWidth: 500,
+    maxHeight: 400,
+    pinned: true
+});
+resizer.on('resize', myHandler);
+</code></pre>
+ * <p>To hide a particular handle, set its display to none in CSS, or through script:<br>
+ * resizer.east.setDisplayed(false);</p>
+ * @constructor
+ * Create a new resizable component
+ * @param {Mixed} el The id or element to resize
+ * @param {Object} config configuration options
+  */
+Ext.Resizable = function(el, config){
+    this.el = Ext.get(el);
+
+    /**
+     * The proxy Element that is resized in place of the real Element during the resize operation.
+     * This may be queried using {@link Ext.Element#getBox} to provide the new area to resize to.
+     * Read only.
+     * @type Ext.Element.
+     * @property proxy
+     */
+    this.proxy = this.el.createProxy({tag: 'div', cls: 'x-resizable-proxy', id: this.el.id + '-rzproxy'}, Ext.getBody());
+    this.proxy.unselectable();
+    this.proxy.enableDisplayMode('block');
+
+    Ext.apply(this, config);
+    
+    if(this.pinned){
+        this.disableTrackOver = true;
+        this.el.addClass('x-resizable-pinned');
+    }
+    // if the element isn't positioned, make it relative
+    var position = this.el.getStyle('position');
+    if(position != 'absolute' && position != 'fixed'){
+        this.el.setStyle('position', 'relative');
+    }
+    if(!this.handles){ // no handles passed, must be legacy style
+        this.handles = 's,e,se';
+        if(this.multiDirectional){
+            this.handles += ',n,w';
+        }
+    }
+    if(this.handles == 'all'){
+        this.handles = 'n s e w ne nw se sw';
+    }
+    var hs = this.handles.split(/\s*?[,;]\s*?| /);
+    var ps = Ext.Resizable.positions;
+    for(var i = 0, len = hs.length; i < len; i++){
+        if(hs[i] && ps[hs[i]]){
+            var pos = ps[hs[i]];
+            this[pos] = new Ext.Resizable.Handle(this, pos);
+        }
+    }
+    // legacy
+    this.corner = this.southeast;
+    
+    if(this.handles.indexOf('n') != -1 || this.handles.indexOf('w') != -1){
+        this.updateBox = true;
+    }   
+    this.activeHandle = null;
+
+    if(this.adjustments == 'auto'){
+        var hw = this.west, he = this.east, hn = this.north, hs = this.south;
+        this.adjustments = [
+            (he.el ? -he.el.getWidth() : 0) + (hw.el ? -hw.el.getWidth() : 0),
+            (hn.el ? -hn.el.getHeight() : 0) + (hs.el ? -hs.el.getHeight() : 0) -1 
+        ];
+    }
+
+    if(this.draggable){
+        this.dd = this.dynamic ? 
+            this.el.initDD(null) : this.el.initDDProxy(null, {dragElId: this.proxy.id});
+        this.dd.setHandleElId(this.el.id);
+    }
+
+    this.addEvents(
+        /**
+         * @event beforeresize
+         * Fired before resize is allowed. Set {@link #enabled} to false to cancel resize.
+         * @param {Ext.Resizable} this
+         * @param {Ext.EventObject} e The mousedown event
+         */
+        'beforeresize',
+        /**
+         * @event resize
+         * Fired after a resize.
+         * @param {Ext.Resizable} this
+         * @param {Number} width The new width
+         * @param {Number} height The new height
+         * @param {Ext.EventObject} e The mouseup event
+         */
+        'resize'
+    );
+    
+    if(this.width !== null && this.height !== null){
+        this.resizeTo(this.width, this.height);
+    }
+    if(Ext.isIE){
+        this.el.dom.style.zoom = 1;
+    }
+    Ext.Resizable.superclass.constructor.call(this);
+};
+
+Ext.extend(Ext.Resizable, Ext.util.Observable, {
+
+    /**
+     * @cfg {Array/String} adjustments String 'auto' or an array [width, height] with values to be <b>added</b> to the
+     * resize operation's new size (defaults to <tt>[0, 0]</tt>)
+     */
+    adjustments : [0, 0],
+    /**
+     * @cfg {Boolean} animate True to animate the resize (not compatible with dynamic sizing, defaults to false)
+     */
+    animate : false,
+    /**
+     * @cfg {Mixed} constrainTo Constrain the resize to a particular element
+     */
+    /**
+     * @cfg {Boolean} draggable Convenience to initialize drag drop (defaults to false)
+     */
+    draggable: false,
+    /**
+     * @cfg {Number} duration Animation duration if animate = true (defaults to 0.35)
+     */
+    duration : 0.35,
+    /**
+     * @cfg {Boolean} dynamic True to resize the element while dragging instead of using a proxy (defaults to false)
+     */
+    dynamic : false,
+    /**
+     * @cfg {String} easing Animation easing if animate = true (defaults to <tt>'easingOutStrong'</tt>)
+     */
+    easing : 'easeOutStrong',
+    /**
+     * @cfg {Boolean} enabled False to disable resizing (defaults to true)
+     */
+    enabled : true,
+    /**
+     * @property enabled Writable. False if resizing is disabled.
+     * @type Boolean 
+     */
+    /**
+     * @cfg {String} handles String consisting of the resize handles to display (defaults to undefined).
+     * Specify either <tt>'all'</tt> or any of <tt>'n s e w ne nw se sw'</tt>.
+     */
+    handles : false,
+    /**
+     * @cfg {Boolean} multiDirectional <b>Deprecated</b>.  Deprecated style of adding multi-direction resize handles.
+     */
+    multiDirectional : false,
+    /**
+     * @cfg {Number} height The height of the element in pixels (defaults to null)
+     */
+    height : null,
+    /**
+     * @cfg {Number} width The width of the element in pixels (defaults to null)
+     */
+    width : null,
+    /**
+     * @cfg {Number} heightIncrement The increment to snap the height resize in pixels
+     * (only applies if <code>{@link #dynamic}==true</code>). Defaults to <tt>0</tt>.
+     */
+    heightIncrement : 0,
+    /**
+     * @cfg {Number} widthIncrement The increment to snap the width resize in pixels
+     * (only applies if <code>{@link #dynamic}==true</code>). Defaults to <tt>0</tt>.
+     */
+    widthIncrement : 0,
+    /**
+     * @cfg {Number} minHeight The minimum height for the element (defaults to 5)
+     */
+    minHeight : 5,
+    /**
+     * @cfg {Number} minWidth The minimum width for the element (defaults to 5)
+     */
+    minWidth : 5,
+    /**
+     * @cfg {Number} maxHeight The maximum height for the element (defaults to 10000)
+     */
+    maxHeight : 10000,
+    /**
+     * @cfg {Number} maxWidth The maximum width for the element (defaults to 10000)
+     */
+    maxWidth : 10000,
+    /**
+     * @cfg {Number} minX The minimum x for the element (defaults to 0)
+     */
+    minX: 0,
+    /**
+     * @cfg {Number} minY The minimum x for the element (defaults to 0)
+     */
+    minY: 0,
+    /**
+     * @cfg {Boolean} pinned True to ensure that the resize handles are always visible, false to display them only when the
+     * user mouses over the resizable borders. This is only applied at config time. (defaults to false)
+     */
+    pinned : false,
+    /**
+     * @cfg {Boolean} preserveRatio True to preserve the original ratio between height
+     * and width during resize (defaults to false)
+     */
+    preserveRatio : false,
+    /**
+     * @cfg {Ext.lib.Region} resizeRegion Constrain the resize to a particular region
+     */
+
+    
+    /**
+     * Perform a manual resize and fires the 'resize' event.
+     * @param {Number} width
+     * @param {Number} height
+     */
+    resizeTo : function(width, height){
+        this.el.setSize(width, height);
+        this.fireEvent('resize', this, width, height, null);
+    },
+
+    // private
+    startSizing : function(e, handle){
+        this.fireEvent('beforeresize', this, e);
+        if(this.enabled){ // 2nd enabled check in case disabled before beforeresize handler
+            e.stopEvent();
+
+            Ext.getDoc().on({
+                scope: this,
+                mousemove: this.onMouseMove,
+                mouseup: {
+                    fn: this.onMouseUp,
+                    single: true,
+                    scope: this
+                }
+            });
+            Ext.getBody().addClass('ux-resizable-handle-' + handle.position);
+
+            this.resizing = true;
+            this.startBox = this.el.getBox();
+            this.startPoint = e.getXY();
+            this.offsets = [(this.startBox.x + this.startBox.width) - this.startPoint[0],
+                            (this.startBox.y + this.startBox.height) - this.startPoint[1]];
+
+            if(this.constrainTo) {
+                var ct = Ext.get(this.constrainTo);
+                this.resizeRegion = ct.getRegion().adjust(
+                    ct.getFrameWidth('t'),
+                    ct.getFrameWidth('l'),
+                    -ct.getFrameWidth('b'),
+                    -ct.getFrameWidth('r')
+                );
+            }
+
+            this.proxy.setStyle('visibility', 'hidden'); // workaround display none
+            this.proxy.show();
+            this.proxy.setBox(this.startBox);
+            if(!this.dynamic){
+                this.proxy.setStyle('visibility', 'visible');
+            }
+        }
+    },
+
+    // private
+    onMouseDown : function(handle, e){
+        if(this.enabled && !this.activeHandle){
+            e.stopEvent();
+            this.activeHandle = handle;
+            this.startSizing(e, handle);
+        }
+    },
+
+    // private
+    onMouseUp : function(e){
+        Ext.getBody().removeClass('ux-resizable-handle-' + this.activeHandle.position)
+            .un('mousemove', this.onMouseMove, this);
+        var size = this.resizeElement();
+        this.resizing = false;
+        this.handleOut(this.activeHandle);
+        this.proxy.hide();
+        this.fireEvent('resize', this, size.width, size.height, e);
+        this.activeHandle = null;
+    },
+
+    // private
+    snap : function(value, inc, min){
+        if(!inc || !value){
+            return value;
+        }
+        var newValue = value;
+        var m = value % inc;
+        if(m > 0){
+            if(m > (inc/2)){
+                newValue = value + (inc-m);
+            }else{
+                newValue = value - m;
+            }
+        }
+        return Math.max(min, newValue);
+    },
+
+    /**
+     * <p>Performs resizing of the associated Element. This method is called internally by this
+     * class, and should not be called by user code.</p>
+     * <p>If a Resizable is being used to resize an Element which encapsulates a more complex UI
+     * component such as a Panel, this method may be overridden by specifying an implementation
+     * as a config option to provide appropriate behaviour at the end of the resize operation on
+     * mouseup, for example resizing the Panel, and relaying the Panel's content.</p>
+     * <p>The new area to be resized to is available by examining the state of the {@link #proxy}
+     * Element. Example:
+<pre><code>
+new Ext.Panel({
+    title: 'Resize me',
+    x: 100,
+    y: 100,
+    renderTo: Ext.getBody(),
+    floating: true,
+    frame: true,
+    width: 400,
+    height: 200,
+    listeners: {
+        render: function(p) {
+            new Ext.Resizable(p.getEl(), {
+                handles: 'all',
+                pinned: true,
+                transparent: true,
+                resizeElement: function() {
+                    var box = this.proxy.getBox();
+                    p.updateBox(box);
+                    if (p.layout) {
+                        p.doLayout();
+                    }
+                    return box;
+                }
+           });
+       }
+    }
+}).show();
+</code></pre>
+     */
+    resizeElement : function(){
+        var box = this.proxy.getBox();
+        if(this.updateBox){
+            this.el.setBox(box, false, this.animate, this.duration, null, this.easing);
+        }else{
+            this.el.setSize(box.width, box.height, this.animate, this.duration, null, this.easing);
+        }
+        if(!this.dynamic){
+            this.proxy.hide();
+        }
+        return box;
+    },
+
+    // private
+    constrain : function(v, diff, m, mx){
+        if(v - diff < m){
+            diff = v - m;    
+        }else if(v - diff > mx){
+            diff = v - mx; 
+        }
+        return diff;                
+    },
+
+    // private
+    onMouseMove : function(e){
+        if(this.enabled && this.activeHandle){
+            try{// try catch so if something goes wrong the user doesn't get hung
+
+            if(this.resizeRegion && !this.resizeRegion.contains(e.getPoint())) {
+                return;
+            }
+
+            //var curXY = this.startPoint;
+            var curSize = this.curSize || this.startBox,
+                x = this.startBox.x, y = this.startBox.y,
+                ox = x, 
+                oy = y,
+                w = curSize.width, 
+                h = curSize.height,
+                ow = w, 
+                oh = h,
+                mw = this.minWidth, 
+                mh = this.minHeight,
+                mxw = this.maxWidth, 
+                mxh = this.maxHeight,
+                wi = this.widthIncrement,
+                hi = this.heightIncrement,
+                eventXY = e.getXY(),
+                diffX = -(this.startPoint[0] - Math.max(this.minX, eventXY[0])),
+                diffY = -(this.startPoint[1] - Math.max(this.minY, eventXY[1])),
+                pos = this.activeHandle.position,
+                tw,
+                th;
+            
+            switch(pos){
+                case 'east':
+                    w += diffX; 
+                    w = Math.min(Math.max(mw, w), mxw);
+                    break;
+                case 'south':
+                    h += diffY;
+                    h = Math.min(Math.max(mh, h), mxh);
+                    break;
+                case 'southeast':
+                    w += diffX; 
+                    h += diffY;
+                    w = Math.min(Math.max(mw, w), mxw);
+                    h = Math.min(Math.max(mh, h), mxh);
+                    break;
+                case 'north':
+                    diffY = this.constrain(h, diffY, mh, mxh);
+                    y += diffY;
+                    h -= diffY;
+                    break;
+                case 'west':
+                    diffX = this.constrain(w, diffX, mw, mxw);
+                    x += diffX;
+                    w -= diffX;
+                    break;
+                case 'northeast':
+                    w += diffX; 
+                    w = Math.min(Math.max(mw, w), mxw);
+                    diffY = this.constrain(h, diffY, mh, mxh);
+                    y += diffY;
+                    h -= diffY;
+                    break;
+                case 'northwest':
+                    diffX = this.constrain(w, diffX, mw, mxw);
+                    diffY = this.constrain(h, diffY, mh, mxh);
+                    y += diffY;
+                    h -= diffY;
+                    x += diffX;
+                    w -= diffX;
+                    break;
+               case 'southwest':
+                    diffX = this.constrain(w, diffX, mw, mxw);
+                    h += diffY;
+                    h = Math.min(Math.max(mh, h), mxh);
+                    x += diffX;
+                    w -= diffX;
+                    break;
+            }
+            
+            var sw = this.snap(w, wi, mw);
+            var sh = this.snap(h, hi, mh);
+            if(sw != w || sh != h){
+                switch(pos){
+                    case 'northeast':
+                        y -= sh - h;
+                    break;
+                    case 'north':
+                        y -= sh - h;
+                        break;
+                    case 'southwest':
+                        x -= sw - w;
+                    break;
+                    case 'west':
+                        x -= sw - w;
+                        break;
+                    case 'northwest':
+                        x -= sw - w;
+                        y -= sh - h;
+                    break;
+                }
+                w = sw;
+                h = sh;
+            }
+            
+            if(this.preserveRatio){
+                switch(pos){
+                    case 'southeast':
+                    case 'east':
+                        h = oh * (w/ow);
+                        h = Math.min(Math.max(mh, h), mxh);
+                        w = ow * (h/oh);
+                       break;
+                    case 'south':
+                        w = ow * (h/oh);
+                        w = Math.min(Math.max(mw, w), mxw);
+                        h = oh * (w/ow);
+                        break;
+                    case 'northeast':
+                        w = ow * (h/oh);
+                        w = Math.min(Math.max(mw, w), mxw);
+                        h = oh * (w/ow);
+                    break;
+                    case 'north':
+                        tw = w;
+                        w = ow * (h/oh);
+                        w = Math.min(Math.max(mw, w), mxw);
+                        h = oh * (w/ow);
+                        x += (tw - w) / 2;
+                        break;
+                    case 'southwest':
+                        h = oh * (w/ow);
+                        h = Math.min(Math.max(mh, h), mxh);
+                        tw = w;
+                        w = ow * (h/oh);
+                        x += tw - w;
+                        break;
+                    case 'west':
+                        th = h;
+                        h = oh * (w/ow);
+                        h = Math.min(Math.max(mh, h), mxh);
+                        y += (th - h) / 2;
+                        tw = w;
+                        w = ow * (h/oh);
+                        x += tw - w;
+                       break;
+                    case 'northwest':
+                        tw = w;
+                        th = h;
+                        h = oh * (w/ow);
+                        h = Math.min(Math.max(mh, h), mxh);
+                        w = ow * (h/oh);
+                        y += th - h;
+                        x += tw - w;
+                        break;
+                        
+                }
+            }
+            this.proxy.setBounds(x, y, w, h);
+            if(this.dynamic){
+                this.resizeElement();
+            }
+            }catch(ex){}
+        }
+    },
+
+    // private
+    handleOver : function(handle){
+        if(this.enabled){
+            Ext.getBody().addClass('ux-resizable-handle-' + handle.position);
+        }
+    },
+
+    // private
+    handleOut : function(handle){
+        if(!this.resizing){
+            Ext.getBody().removeClass('ux-resizable-handle-' + handle.position);
+        }
+    },
+    
+    /**
+     * Returns the element this component is bound to.
+     * @return {Ext.Element}
+     */
+    getEl : function(){
+        return this.el;
+    },
+
+    /**
+     * Destroys this resizable. If the element was wrapped and 
+     * removeEl is not true then the element remains.
+     * @param {Boolean} removeEl (optional) true to remove the element from the DOM
+     */
+    destroy : function(removeEl){
+        Ext.destroy(this.dd, this.proxy);
+        this.proxy = null;
+        
+        var ps = Ext.Resizable.positions;
+        for(var k in ps){
+            if(typeof ps[k] != 'function' && this[ps[k]]){
+                this[ps[k]].destroy();
+            }
+        }
+        if(removeEl){
+            this.el.update('');
+            Ext.destroy(this.el);
+            this.el = null;
+        }
+        this.purgeListeners();
+    },
+
+    syncHandleHeight : function(){
+        var h = this.el.getHeight(true);
+        if(this.west.el){
+            this.west.el.setHeight(h);
+        }
+        if(this.east.el){
+            this.east.el.setHeight(h);
+        }
+    }
+});
+
+// private
+// hash to map config positions to true positions
+Ext.Resizable.positions = {
+    n: 'north', s: 'south', e: 'east', w: 'west', se: 'southeast', sw: 'southwest', nw: 'northwest', ne: 'northeast'
+};
+Ext.Resizable.cfg = {
+    north: {left: 7, right: -7, height: 7},
+    south: {left: 7, right: -7, top: -7},
+    east: {top: 7, bottom: -7, left: -7},
+    west: {top: 7, bottom: -7, width: 7},
+    southeast: {top: -7, left: -7},
+    southwest: {top: -7, width: 7},
+    northwest: {height: 7, width: 7},
+    northeast: {left: -7, height: 7}
+};
+
+// private
+Ext.Resizable.Handle = function(rz, pos){
+    this.position = pos;
+    this.rz = rz;
+    var cfg = Ext.Resizable.cfg[pos] || Ext.Resizable.cfg[Ext.Resizable.positions[pos]];
+    this.ez = new Ext.ux.EventZone(Ext.apply({
+        position: pos,
+        el: rz.el
+    }, cfg));
+    this.ez.on({
+        mousedown: this.onMouseDown,
+        mouseenter: this.onMouseOver,
+        mouseleave: this.onMouseOut,
+        scope: this
+    });
+};
+
+// private
+Ext.Resizable.Handle.prototype = {
+    cursor: 'move',
+
+    // private
+    afterResize : function(rz){
+        // do nothing    
+    },
+    // private
+    onMouseDown : function(e){
+        this.rz.onMouseDown(this, e);
+    },
+    // private
+    onMouseOver : function(e){
+        this.rz.handleOver(this, e);
+    },
+    // private
+    onMouseOut : function(e){
+        this.rz.handleOut(this, e);
+    },
+    // private
+    destroy : function(){
+        Ext.destroy(this.el);
+        this.el = null;
+    }
+};
+
+/**
+*
+* Ext.ux.elasticTextArea Extension Class for Ext 3.x Library
+*
+* @author  Steffen Kamper
+*
+* @license Ext.ux.elasticTextArea is licensed under the terms of
+* the Open Source LGPL 3.0 license.  Commercial use is permitted to the extent
+* that the code/component(s) do NOT become part of another Open Source or Commercially
+* licensed development library or toolkit without explicit permission.
+* 
+* License details: http://www.gnu.org/licenses/lgpl.html
+*
+*/
+Ext.ux.elasticTextArea = function(){
+    
+    var defaultConfig = function(){
+        return {
+            minHeight : 0
+            ,maxHeight : 0
+            ,growBy: 12
+        }
+    }
+    
+    var processOptions = function(config){
+        var o = defaultConfig();
+        var options = {};
+        Ext.apply(options, config, o);
+        
+        return options ;
+    }
+    
+    return {
+        div : null
+        ,applyTo: function(elementId, options){
+        
+            var el = Ext.get(elementId);
+            var width = el.getWidth();
+            var height = el.getHeight();
+            
+            var styles = el.getStyles('padding-top', 'padding-bottom', 'padding-left', 'padding-right', 'line-height', 'font-size', 'font-family', 'font-weight');
+
+            if(! this.div){
+                var options = processOptions(options);
+                
+                this.div = Ext.DomHelper.append(Ext.getBody() || document.body, {
+                    'id':elementId + '-preview-div'
+                    ,'tag' : 'div'
+                    ,'background': 'red'
+                    ,'style' : 'position: absolute; top: -100000px; left: -100000px;'
+                }, true)
+                Ext.DomHelper.applyStyles(this.div, styles);
+                
+                el.on('keyup', function() {
+                        this.applyTo(elementId, options);
+                }, this);
+            }
+            this.div.setWidth(parseInt(el.getStyle('width')));
+            //replace \n with <br>&nbsp; so that the enter key can trigger and height increase
+            //but first remove all previous entries, so that the height mesurement can be as accurate as possible
+            this.div.update( 
+                    el.dom.value.replace(/<br \/>&nbsp;/, '<br />')
+                                .replace(/<|>/g, ' ')
+                                .replace(/&/g,"&amp;")
+                                .replace(/\n/g, '<br />&nbsp;') 
+                    );
+            
+                       var growBy = parseInt(el.getStyle('line-height'));
+                       growBy = growBy ? growBy + 1 : 1;
+                       if (growBy === 1) {
+                               growBy = options.growBy;
+                       }
+                       var textHeight = this.div.getHeight();
+                       textHeight = textHeight ? textHeight + growBy : growBy;
+            
+            if ( (textHeight > options.maxHeight ) && (options.maxHeight > 0) ){
+                textHeight = options.maxHeight ;
+                el.setStyle('overflow', 'auto');
+            }
+            if ( (textHeight < options.minHeight ) && (options.minHeight > 0) ) {
+                textHeight = options.minHeight ;
+                el.setStyle('overflow', 'auto');
+            }
+            
+            el.setHeight(textHeight , true);
+        }
+    }
+}
index de7ab6d..3893368 100644 (file)
@@ -6,18 +6,16 @@
  */
 /**
  * @class Ext.ux.TabCloseMenu
- * @extends Object
+ * @extends Object 
  * Plugin (ptype = 'tabclosemenu') for adding a close context menu to tabs. Note that the menu respects
  * the closable configuration on the tab. As such, commands like remove others and remove all will not
  * remove items that are not closable.
- *
+ * 
  * @constructor
  * @param {Object} config The configuration options
  * @ptype tabclosemenu
  */
-Ext.define('Ext.ux.TabCloseMenu', {
-    alias: ['plugin.tabclosemenu'],
-
+Ext.ux.TabCloseMenu = Ext.extend(Object, {
     /**
      * @cfg {String} closeTabText
      * The text for closing the current tab. Defaults to <tt>'Close Tab'</tt>.
@@ -29,10 +27,10 @@ Ext.define('Ext.ux.TabCloseMenu', {
      * The text for closing all tabs except the current one. Defaults to <tt>'Close Other Tabs'</tt>.
      */
     closeOtherTabsText: 'Close Other Tabs',
-
+    
     /**
      * @cfg {Boolean} showCloseAll
-     * Indicates whether to show the 'Close All' option. Defaults to <tt>true</tt>.
+     * Indicates whether to show the 'Close All' option. Defaults to <tt>true</tt>. 
      */
     showCloseAll: true,
 
@@ -41,13 +39,13 @@ Ext.define('Ext.ux.TabCloseMenu', {
      * <p>The text for closing all tabs. Defaults to <tt>'Close All Tabs'</tt>.
      */
     closeAllTabsText: 'Close All Tabs',
-
+    
     /**
         * @cfg {Array} custom menu entries
         */
        customMenuEntries: [],
 
-
+    
     constructor : function(config){
         Ext.apply(this, config || {});
     },
@@ -61,12 +59,12 @@ Ext.define('Ext.ux.TabCloseMenu', {
             destroy: this.destroy
         });
     },
-
+    
     destroy : function(){
         Ext.destroy(this.menu);
         delete this.menu;
         delete this.tabs;
-        delete this.active;
+        delete this.active;    
     },
 
     // private
@@ -76,7 +74,7 @@ Ext.define('Ext.ux.TabCloseMenu', {
             disableAll = true,
             disableOthers = true,
             closeAll = m.getComponent('closeall');
-
+        
         m.getComponent('close').setDisabled(!item.closable);
         tabs.items.each(function(){
             if(this.closable){
@@ -92,11 +90,11 @@ Ext.define('Ext.ux.TabCloseMenu', {
         if(closeAll){
             closeAll.setDisabled(disableAll);
         }
-
+        
         e.stopEvent();
         m.showAt(e.getPoint());
     },
-
+    
     createMenu : function(){
         if(!this.menu){
             var items = [{
@@ -127,33 +125,33 @@ Ext.define('Ext.ux.TabCloseMenu', {
                        items.push(item);
                });
             }
-
-            this.menu = Ext.create('Ext.menu.Menu', {
+            
+            this.menu = new Ext.menu.Menu({
                 items: items
             });
         }
         return this.menu;
     },
-
+    
     onClose : function(){
         this.tabs.remove(this.active);
     },
-
+    
     onCloseOthers : function(){
         this.doClose(true);
     },
-
+    
     onCloseAll : function(){
         this.doClose(false);
     },
-
+    
     doClose : function(excludeActive){
         var items = [];
         this.tabs.items.each(function(item){
             if(item.closable){
                 if(!excludeActive || item != this.active){
                     items.push(item);
-                }
+                }    
             }
         }, this);
         Ext.each(items, function(item){
@@ -161,3 +159,5 @@ Ext.define('Ext.ux.TabCloseMenu', {
         }, this);
     }
 });
+
+Ext.preg('tabclosemenu', Ext.ux.TabCloseMenu);
index 0835616..b4f3df2 100644 (file)
@@ -76,13 +76,13 @@ TYPO3.Flashmessage = function() {
                display : function(severity, title, message, duration) {
                        duration = duration || 5;
                        if (!messageContainer) {
-                               messageContainer = Ext.core.DomHelper.insertFirst(document.body, {
+                               messageContainer = Ext.DomHelper.insertFirst(document.body, {
                                        id   : 'msg-div',
                                        style: 'position:absolute;z-index:10000'
                                }, true);
                        }
 
-                       var box = Ext.core.DomHelper.append(messageContainer, {
+                       var box = Ext.DomHelper.append(messageContainer, {
                                html: createBox(severities[severity], title, message)
                        }, true);
                        messageContainer.alignTo(document, 't-t');
diff --git a/t3lib/js/extjs/ux/resize.css b/t3lib/js/extjs/ux/resize.css
new file mode 100644 (file)
index 0000000..c4ff47c
--- /dev/null
@@ -0,0 +1,68 @@
+.ux-resizable-handle-east, .ux-resizable-handle-east textarea {
+    cursor: e-resize;
+}
+
+.ux-resizable-handle-south, .ux-resizable-handle-south textarea {
+    cursor: s-resize;
+}
+
+.ux-resizable-handle-west, .ux-resizable-handle-west textarea {
+    cursor: w-resize;
+}
+
+.ux-resizable-handle-north, .ux-resizable-handle-north textarea {
+    cursor: n-resize;
+}
+
+.ux-resizable-handle-southeast, .ux-resizable-handle-southeast textarea {
+    cursor: se-resize;
+}
+
+.ux-resizable-handle-northwest, .ux-resizable-handle-northwest textarea {
+    cursor: nw-resize;
+}
+
+.ux-resizable-handle-northeast, .ux-resizable-handle-northeast textarea {
+    cursor: ne-resize;
+}
+
+.ux-resizable-handle-southwest, .ux-resizable-handle-southwest textarea {
+    cursor: sw-resize;
+}
+.ux-resizable-handle-east, .ux-resizable-handle-east textarea {
+    cursor: e-resize;
+}
+
+.ux-resizable-handle-south, .ux-resizable-handle-south textarea {
+    cursor: s-resize;
+}
+
+.ux-resizable-handle-west, .ux-resizable-handle-west textarea {
+    cursor: w-resize;
+}
+
+.ux-resizable-handle-north, .ux-resizable-handle-north textarea {
+    cursor: n-resize;
+}
+
+.ux-resizable-handle-southeast, .ux-resizable-handle-southeast textarea {
+    cursor: se-resize;
+}
+
+.ux-resizable-handle-northwest, .ux-resizable-handle-northwest textarea {
+    cursor: nw-resize;
+}
+
+.ux-resizable-handle-northeast, .ux-resizable-handle-northeast textarea {
+    cursor: ne-resize;
+}
+
+.ux-resizable-handle-southwest, .ux-resizable-handle-southwest textarea {
+    cursor: sw-resize;
+}
+
+textarea.resizable {
+       background-image: url(resize.gif);
+       background-position: bottom right;
+       background-repeat: no-repeat;
+}
\ No newline at end of file
diff --git a/t3lib/js/extjs/ux/resize.gif b/t3lib/js/extjs/ux/resize.gif
new file mode 100644 (file)
index 0000000..89b82d7
Binary files /dev/null and b/t3lib/js/extjs/ux/resize.gif differ
diff --git a/typo3/sysext/t3skin/stylesheets/structure/element_datetime_picker.css b/typo3/sysext/t3skin/stylesheets/structure/element_datetime_picker.css
deleted file mode 100644 (file)
index 09c48ce..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-/* - - - - - - - - - - - - - - - - - - - - -
-Element Date Time Picker
-
-- - - - - - - - - - - - - - - - - - - - - */
-
-.typo3-datetime-picker-footer .typo3-datetime-picker-hour,
-.typo3-datetime-picker-footer .typo3-datetime-picker-minute {
-       margin-top: 4px;
-}
-.typo3-datetime-picker-footer .typo3-datetime-picker-hour input,
-.typo3-datetime-picker-footer .typo3-datetime-picker-minute input {
-       text-align: right;
-       width: 25px !important;
-}