Upgrade to ExtJS 3.1.1 - Released 02/08/2010
[extjs.git] / src / widgets / Resizable.js
index a746fa4..4746905 100644 (file)
@@ -1,9 +1,15 @@
 /*!
- * Ext JS Library 3.0.3
- * Copyright(c) 2006-2009 Ext JS, LLC
+ * Ext JS Library 3.1.1
+ * Copyright(c) 2006-2010 Ext JS, LLC
  * licensing@extjs.com
  * http://www.extjs.com/license
  */
+/*!\r
+ * Ext JS Library 3.1.1\r
+ * Copyright(c) 2006-2010 Ext JS, LLC\r
+ * licensing@extjs.com\r
+ * http://www.extjs.com/license\r
+ */\r
 /**\r
  * @class Ext.Resizable\r
  * @extends Ext.util.Observable\r
@@ -44,132 +50,134 @@ resizer.on('resize', myHandler);
  * @param {Mixed} el The id or element to resize\r
  * @param {Object} config configuration options\r
   */\r
-Ext.Resizable = function(el, config){\r
-    this.el = Ext.get(el);\r
+Ext.Resizable = Ext.extend(Ext.util.Observable, {\r
     \r
-    if(config && config.wrap){\r
-        config.resizeChild = this.el;\r
-        this.el = this.el.wrap(typeof config.wrap == 'object' ? config.wrap : {cls:'xresizable-wrap'});\r
-        this.el.id = this.el.dom.id = config.resizeChild.id + '-rzwrap';\r
-        this.el.setStyle('overflow', 'hidden');\r
-        this.el.setPositioning(config.resizeChild.getPositioning());\r
-        config.resizeChild.clearPositioning();\r
-        if(!config.width || !config.height){\r
-            var csize = config.resizeChild.getSize();\r
-            this.el.setSize(csize.width, csize.height);\r
-        }\r
-        if(config.pinned && !config.adjustments){\r
-            config.adjustments = 'auto';\r
+    constructor: function(el, config){\r
+        this.el = Ext.get(el);\r
+        if(config && config.wrap){\r
+            config.resizeChild = this.el;\r
+            this.el = this.el.wrap(typeof config.wrap == 'object' ? config.wrap : {cls:'xresizable-wrap'});\r
+            this.el.id = this.el.dom.id = config.resizeChild.id + '-rzwrap';\r
+            this.el.setStyle('overflow', 'hidden');\r
+            this.el.setPositioning(config.resizeChild.getPositioning());\r
+            config.resizeChild.clearPositioning();\r
+            if(!config.width || !config.height){\r
+                var csize = config.resizeChild.getSize();\r
+                this.el.setSize(csize.width, csize.height);\r
+            }\r
+            if(config.pinned && !config.adjustments){\r
+                config.adjustments = 'auto';\r
+            }\r
         }\r
-    }\r
-\r
-    /**\r
-     * The proxy Element that is resized in place of the real Element during the resize operation.\r
-     * This may be queried using {@link Ext.Element#getBox} to provide the new area to resize to.\r
-     * Read only.\r
-     * @type Ext.Element.\r
-     * @property proxy\r
-     */\r
-    this.proxy = this.el.createProxy({tag: 'div', cls: 'x-resizable-proxy', id: this.el.id + '-rzproxy'}, Ext.getBody());\r
-    this.proxy.unselectable();\r
-    this.proxy.enableDisplayMode('block');\r
-\r
-    Ext.apply(this, config);\r
     \r
-    if(this.pinned){\r
-        this.disableTrackOver = true;\r
-        this.el.addClass('x-resizable-pinned');\r
-    }\r
-    // if the element isn't positioned, make it relative\r
-    var position = this.el.getStyle('position');\r
-    if(position != 'absolute' && position != 'fixed'){\r
-        this.el.setStyle('position', 'relative');\r
-    }\r
-    if(!this.handles){ // no handles passed, must be legacy style\r
-        this.handles = 's,e,se';\r
-        if(this.multiDirectional){\r
-            this.handles += ',n,w';\r
+        /**\r
+         * The proxy Element that is resized in place of the real Element during the resize operation.\r
+         * This may be queried using {@link Ext.Element#getBox} to provide the new area to resize to.\r
+         * Read only.\r
+         * @type Ext.Element.\r
+         * @property proxy\r
+         */\r
+        this.proxy = this.el.createProxy({tag: 'div', cls: 'x-resizable-proxy', id: this.el.id + '-rzproxy'}, Ext.getBody());\r
+        this.proxy.unselectable();\r
+        this.proxy.enableDisplayMode('block');\r
+    \r
+        Ext.apply(this, config);\r
+        \r
+        if(this.pinned){\r
+            this.disableTrackOver = true;\r
+            this.el.addClass('x-resizable-pinned');\r
         }\r
-    }\r
-    if(this.handles == 'all'){\r
-        this.handles = 'n s e w ne nw se sw';\r
-    }\r
-    var hs = this.handles.split(/\s*?[,;]\s*?| /);\r
-    var ps = Ext.Resizable.positions;\r
-    for(var i = 0, len = hs.length; i < len; i++){\r
-        if(hs[i] && ps[hs[i]]){\r
-            var pos = ps[hs[i]];\r
-            this[pos] = new Ext.Resizable.Handle(this, pos, this.disableTrackOver, this.transparent);\r
+        // if the element isn't positioned, make it relative\r
+        var position = this.el.getStyle('position');\r
+        if(position != 'absolute' && position != 'fixed'){\r
+            this.el.setStyle('position', 'relative');\r
         }\r
-    }\r
-    // legacy\r
-    this.corner = this.southeast;\r
-    \r
-    if(this.handles.indexOf('n') != -1 || this.handles.indexOf('w') != -1){\r
-        this.updateBox = true;\r
-    }   \r
-   \r
-    this.activeHandle = null;\r
-    \r
-    if(this.resizeChild){\r
-        if(typeof this.resizeChild == 'boolean'){\r
-            this.resizeChild = Ext.get(this.el.dom.firstChild, true);\r
+        if(!this.handles){ // no handles passed, must be legacy style\r
+            this.handles = 's,e,se';\r
+            if(this.multiDirectional){\r
+                this.handles += ',n,w';\r
+            }\r
+        }\r
+        if(this.handles == 'all'){\r
+            this.handles = 'n s e w ne nw se sw';\r
+        }\r
+        var hs = this.handles.split(/\s*?[,;]\s*?| /);\r
+        var ps = Ext.Resizable.positions;\r
+        for(var i = 0, len = hs.length; i < len; i++){\r
+            if(hs[i] && ps[hs[i]]){\r
+                var pos = ps[hs[i]];\r
+                this[pos] = new Ext.Resizable.Handle(this, pos, this.disableTrackOver, this.transparent, this.handleCls);\r
+            }\r
+        }\r
+        // legacy\r
+        this.corner = this.southeast;\r
+        \r
+        if(this.handles.indexOf('n') != -1 || this.handles.indexOf('w') != -1){\r
+            this.updateBox = true;\r
+        }   \r
+       \r
+        this.activeHandle = null;\r
+        \r
+        if(this.resizeChild){\r
+            if(typeof this.resizeChild == 'boolean'){\r
+                this.resizeChild = Ext.get(this.el.dom.firstChild, true);\r
+            }else{\r
+                this.resizeChild = Ext.get(this.resizeChild, true);\r
+            }\r
+        }\r
+        \r
+        if(this.adjustments == 'auto'){\r
+            var rc = this.resizeChild;\r
+            var hw = this.west, he = this.east, hn = this.north, hs = this.south;\r
+            if(rc && (hw || hn)){\r
+                rc.position('relative');\r
+                rc.setLeft(hw ? hw.el.getWidth() : 0);\r
+                rc.setTop(hn ? hn.el.getHeight() : 0);\r
+            }\r
+            this.adjustments = [\r
+                (he ? -he.el.getWidth() : 0) + (hw ? -hw.el.getWidth() : 0),\r
+                (hn ? -hn.el.getHeight() : 0) + (hs ? -hs.el.getHeight() : 0) -1 \r
+            ];\r
+        }\r
+        \r
+        if(this.draggable){\r
+            this.dd = this.dynamic ? \r
+                this.el.initDD(null) : this.el.initDDProxy(null, {dragElId: this.proxy.id});\r
+            this.dd.setHandleElId(this.resizeChild ? this.resizeChild.id : this.el.id);\r
+            if(this.constrainTo){\r
+                this.dd.constrainTo(this.constrainTo);\r
+            }\r
+        }\r
+        \r
+        this.addEvents(\r
+            /**\r
+             * @event beforeresize\r
+             * Fired before resize is allowed. Set {@link #enabled} to false to cancel resize.\r
+             * @param {Ext.Resizable} this\r
+             * @param {Ext.EventObject} e The mousedown event\r
+             */\r
+            'beforeresize',\r
+            /**\r
+             * @event resize\r
+             * Fired after a resize.\r
+             * @param {Ext.Resizable} this\r
+             * @param {Number} width The new width\r
+             * @param {Number} height The new height\r
+             * @param {Ext.EventObject} e The mouseup event\r
+             */\r
+            'resize'\r
+        );\r
+        \r
+        if(this.width !== null && this.height !== null){\r
+            this.resizeTo(this.width, this.height);\r
         }else{\r
-            this.resizeChild = Ext.get(this.resizeChild, true);\r
+            this.updateChildSize();\r
         }\r
-    }\r
-    \r
-    if(this.adjustments == 'auto'){\r
-        var rc = this.resizeChild;\r
-        var hw = this.west, he = this.east, hn = this.north, hs = this.south;\r
-        if(rc && (hw || hn)){\r
-            rc.position('relative');\r
-            rc.setLeft(hw ? hw.el.getWidth() : 0);\r
-            rc.setTop(hn ? hn.el.getHeight() : 0);\r
+        if(Ext.isIE){\r
+            this.el.dom.style.zoom = 1;\r
         }\r
-        this.adjustments = [\r
-            (he ? -he.el.getWidth() : 0) + (hw ? -hw.el.getWidth() : 0),\r
-            (hn ? -hn.el.getHeight() : 0) + (hs ? -hs.el.getHeight() : 0) -1 \r
-        ];\r
-    }\r
-    \r
-    if(this.draggable){\r
-        this.dd = this.dynamic ? \r
-            this.el.initDD(null) : this.el.initDDProxy(null, {dragElId: this.proxy.id});\r
-        this.dd.setHandleElId(this.resizeChild ? this.resizeChild.id : this.el.id);\r
-    }\r
-    \r
-    this.addEvents(\r
-        /**\r
-         * @event beforeresize\r
-         * Fired before resize is allowed. Set {@link #enabled} to false to cancel resize.\r
-         * @param {Ext.Resizable} this\r
-         * @param {Ext.EventObject} e The mousedown event\r
-         */\r
-        'beforeresize',\r
-        /**\r
-         * @event resize\r
-         * Fired after a resize.\r
-         * @param {Ext.Resizable} this\r
-         * @param {Number} width The new width\r
-         * @param {Number} height The new height\r
-         * @param {Ext.EventObject} e The mouseup event\r
-         */\r
-        'resize'\r
-    );\r
-    \r
-    if(this.width !== null && this.height !== null){\r
-        this.resizeTo(this.width, this.height);\r
-    }else{\r
-        this.updateChildSize();\r
-    }\r
-    if(Ext.isIE){\r
-        this.el.dom.style.zoom = 1;\r
-    }\r
-    Ext.Resizable.superclass.constructor.call(this);\r
-};\r
-\r
-Ext.extend(Ext.Resizable, Ext.util.Observable, {\r
+        Ext.Resizable.superclass.constructor.call(this);    \r
+    },\r
 \r
     /**\r
      * @cfg {Array/String} adjustments String 'auto' or an array [width, height] with values to be <b>added</b> to the\r
@@ -287,6 +295,9 @@ Ext.extend(Ext.Resizable, Ext.util.Observable, {
      * @cfg {Boolean} wrap True to wrap an element with a div if needed (required for textareas and images, defaults to false)\r
      * in favor of the handles config option (defaults to false)\r
      */\r
+    /**\r
+     * @cfg {String} handleCls A css class to add to each handle. Defaults to <tt>''</tt>.\r
+     */\r
 \r
     \r
     /**\r
@@ -457,6 +468,10 @@ new Ext.Panel({
         if(!this.dynamic){\r
             this.proxy.hide();\r
         }\r
+        if(this.draggable && this.constrainTo){\r
+            this.dd.resetConstraints();\r
+            this.dd.constrainTo(this.constrainTo);\r
+        }\r
         return box;\r
     },\r
 \r
@@ -707,35 +722,36 @@ Ext.Resizable.positions = {
     n: 'north', s: 'south', e: 'east', w: 'west', se: 'southeast', sw: 'southwest', nw: 'northwest', ne: 'northeast'\r
 };\r
 \r
-// private\r
-Ext.Resizable.Handle = function(rz, pos, disableTrackOver, transparent){\r
-    if(!this.tpl){\r
-        // only initialize the template if resizable is used\r
-        var tpl = Ext.DomHelper.createTemplate(\r
-            {tag: 'div', cls: 'x-resizable-handle x-resizable-handle-{0}'}\r
-        );\r
-        tpl.compile();\r
-        Ext.Resizable.Handle.prototype.tpl = tpl;\r
-    }\r
-    this.position = pos;\r
-    this.rz = rz;\r
-    this.el = this.tpl.append(rz.el.dom, [this.position], true);\r
-    this.el.unselectable();\r
-    if(transparent){\r
-        this.el.setOpacity(0);\r
-    }\r
-    this.el.on('mousedown', this.onMouseDown, this);\r
-    if(!disableTrackOver){\r
-        this.el.on({\r
-            scope: this,\r
-            mouseover: this.onMouseOver,\r
-            mouseout: this.onMouseOut\r
-        });\r
-    }\r
-};\r
-\r
-// private\r
-Ext.Resizable.Handle.prototype = {\r
+Ext.Resizable.Handle = Ext.extend(Object, {\r
+    constructor : function(rz, pos, disableTrackOver, transparent, cls){\r
+       if(!this.tpl){\r
+            // only initialize the template if resizable is used\r
+            var tpl = Ext.DomHelper.createTemplate(\r
+                {tag: 'div', cls: 'x-resizable-handle x-resizable-handle-{0}'}\r
+            );\r
+            tpl.compile();\r
+            Ext.Resizable.Handle.prototype.tpl = tpl;\r
+        }\r
+        this.position = pos;\r
+        this.rz = rz;\r
+        this.el = this.tpl.append(rz.el.dom, [this.position], true);\r
+        this.el.unselectable();\r
+        if(transparent){\r
+            this.el.setOpacity(0);\r
+        }\r
+        if(!Ext.isEmpty(cls)){\r
+            this.el.addClass(cls);    \r
+        }\r
+        this.el.on('mousedown', this.onMouseDown, this);\r
+        if(!disableTrackOver){\r
+            this.el.on({\r
+                scope: this,\r
+                mouseover: this.onMouseOver,\r
+                mouseout: this.onMouseOut\r
+            });\r
+        }        \r
+    },\r
+    \r
     // private\r
     afterResize : function(rz){\r
         // do nothing    \r
@@ -757,4 +773,4 @@ Ext.Resizable.Handle.prototype = {
         Ext.destroy(this.el);\r
         this.el = null;\r
     }\r
-};\r
+});\r