Resizable.js
上传用户:shuoshiled
上传日期:2018-01-28
资源大小:10124k
文件大小:25k
源码类别:

中间件编程

开发平台:

JavaScript

  1. /*!  * Ext JS Library 3.0.0  * Copyright(c) 2006-2009 Ext JS, LLC  * licensing@extjs.com  * http://www.extjs.com/license  */ /**
  2.  * @class Ext.Resizable
  3.  * @extends Ext.util.Observable
  4.  * <p>Applies drag handles to an element to make it resizable. The drag handles are inserted into the element 
  5.  * and positioned absolute. Some elements, such as a textarea or image, don't support this. To overcome that, you can wrap
  6.  * the textarea in a div and set 'resizeChild' to true (or to the id of the element), <b>or</b> set wrap:true in your config and
  7.  * the element will be wrapped for you automatically.</p>
  8.  * <p>Here is the list of valid resize handles:</p>
  9.  * <pre>
  10. Value   Description
  11. ------  -------------------
  12.  'n'     north
  13.  's'     south
  14.  'e'     east
  15.  'w'     west
  16.  'nw'    northwest
  17.  'sw'    southwest
  18.  'se'    southeast
  19.  'ne'    northeast
  20.  'all'   all
  21. </pre>
  22.  * <p>Here's an example showing the creation of a typical Resizable:</p>
  23.  * <pre><code>
  24. var resizer = new Ext.Resizable('element-id', {
  25.     handles: 'all',
  26.     minWidth: 200,
  27.     minHeight: 100,
  28.     maxWidth: 500,
  29.     maxHeight: 400,
  30.     pinned: true
  31. });
  32. resizer.on('resize', myHandler);
  33. </code></pre>
  34.  * <p>To hide a particular handle, set its display to none in CSS, or through script:<br>
  35.  * resizer.east.setDisplayed(false);</p>
  36.  * @constructor
  37.  * Create a new resizable component
  38.  * @param {Mixed} el The id or element to resize
  39.  * @param {Object} config configuration options
  40.   */
  41. Ext.Resizable = function(el, config){
  42.     this.el = Ext.get(el);
  43.     
  44.     if(config && config.wrap){
  45.         config.resizeChild = this.el;
  46.         this.el = this.el.wrap(typeof config.wrap == 'object' ? config.wrap : {cls:'xresizable-wrap'});
  47.         this.el.id = this.el.dom.id = config.resizeChild.id + '-rzwrap';
  48.         this.el.setStyle('overflow', 'hidden');
  49.         this.el.setPositioning(config.resizeChild.getPositioning());
  50.         config.resizeChild.clearPositioning();
  51.         if(!config.width || !config.height){
  52.             var csize = config.resizeChild.getSize();
  53.             this.el.setSize(csize.width, csize.height);
  54.         }
  55.         if(config.pinned && !config.adjustments){
  56.             config.adjustments = 'auto';
  57.         }
  58.     }
  59.     /**
  60.      * The proxy Element that is resized in place of the real Element during the resize operation.
  61.      * This may be queried using {@link Ext.Element#getBox} to provide the new area to resize to.
  62.      * Read only.
  63.      * @type Ext.Element.
  64.      * @property proxy
  65.      */
  66.     this.proxy = this.el.createProxy({tag: 'div', cls: 'x-resizable-proxy', id: this.el.id + '-rzproxy'}, Ext.getBody());
  67.     this.proxy.unselectable();
  68.     this.proxy.enableDisplayMode('block');
  69.     Ext.apply(this, config);
  70.     
  71.     if(this.pinned){
  72.         this.disableTrackOver = true;
  73.         this.el.addClass('x-resizable-pinned');
  74.     }
  75.     // if the element isn't positioned, make it relative
  76.     var position = this.el.getStyle('position');
  77.     if(position != 'absolute' && position != 'fixed'){
  78.         this.el.setStyle('position', 'relative');
  79.     }
  80.     if(!this.handles){ // no handles passed, must be legacy style
  81.         this.handles = 's,e,se';
  82.         if(this.multiDirectional){
  83.             this.handles += ',n,w';
  84.         }
  85.     }
  86.     if(this.handles == 'all'){
  87.         this.handles = 'n s e w ne nw se sw';
  88.     }
  89.     var hs = this.handles.split(/s*?[,;]s*?| /);
  90.     var ps = Ext.Resizable.positions;
  91.     for(var i = 0, len = hs.length; i < len; i++){
  92.         if(hs[i] && ps[hs[i]]){
  93.             var pos = ps[hs[i]];
  94.             this[pos] = new Ext.Resizable.Handle(this, pos, this.disableTrackOver, this.transparent);
  95.         }
  96.     }
  97.     // legacy
  98.     this.corner = this.southeast;
  99.     
  100.     if(this.handles.indexOf('n') != -1 || this.handles.indexOf('w') != -1){
  101.         this.updateBox = true;
  102.     }   
  103.    
  104.     this.activeHandle = null;
  105.     
  106.     if(this.resizeChild){
  107.         if(typeof this.resizeChild == 'boolean'){
  108.             this.resizeChild = Ext.get(this.el.dom.firstChild, true);
  109.         }else{
  110.             this.resizeChild = Ext.get(this.resizeChild, true);
  111.         }
  112.     }
  113.     
  114.     if(this.adjustments == 'auto'){
  115.         var rc = this.resizeChild;
  116.         var hw = this.west, he = this.east, hn = this.north, hs = this.south;
  117.         if(rc && (hw || hn)){
  118.             rc.position('relative');
  119.             rc.setLeft(hw ? hw.el.getWidth() : 0);
  120.             rc.setTop(hn ? hn.el.getHeight() : 0);
  121.         }
  122.         this.adjustments = [
  123.             (he ? -he.el.getWidth() : 0) + (hw ? -hw.el.getWidth() : 0),
  124.             (hn ? -hn.el.getHeight() : 0) + (hs ? -hs.el.getHeight() : 0) -1 
  125.         ];
  126.     }
  127.     
  128.     if(this.draggable){
  129.         this.dd = this.dynamic ? 
  130.             this.el.initDD(null) : this.el.initDDProxy(null, {dragElId: this.proxy.id});
  131.         this.dd.setHandleElId(this.resizeChild ? this.resizeChild.id : this.el.id);
  132.     }
  133.     
  134.     this.addEvents(
  135.         /**
  136.          * @event beforeresize
  137.          * Fired before resize is allowed. Set {@link #enabled} to false to cancel resize.
  138.          * @param {Ext.Resizable} this
  139.          * @param {Ext.EventObject} e The mousedown event
  140.          */
  141.         'beforeresize',
  142.         /**
  143.          * @event resize
  144.          * Fired after a resize.
  145.          * @param {Ext.Resizable} this
  146.          * @param {Number} width The new width
  147.          * @param {Number} height The new height
  148.          * @param {Ext.EventObject} e The mouseup event
  149.          */
  150.         'resize'
  151.     );
  152.     
  153.     if(this.width !== null && this.height !== null){
  154.         this.resizeTo(this.width, this.height);
  155.     }else{
  156.         this.updateChildSize();
  157.     }
  158.     if(Ext.isIE){
  159.         this.el.dom.style.zoom = 1;
  160.     }
  161.     Ext.Resizable.superclass.constructor.call(this);
  162. };
  163. Ext.extend(Ext.Resizable, Ext.util.Observable, {
  164.     /**
  165.      * @cfg {Array/String} adjustments String 'auto' or an array [width, height] with values to be <b>added</b> to the
  166.      * resize operation's new size (defaults to <tt>[0, 0]</tt>)
  167.      */
  168.     adjustments : [0, 0],
  169.     /**
  170.      * @cfg {Boolean} animate True to animate the resize (not compatible with dynamic sizing, defaults to false)
  171.      */
  172.     animate : false,
  173.     /**
  174.      * @cfg {Mixed} constrainTo Constrain the resize to a particular element
  175.      */
  176.     /**
  177.      * @cfg {Boolean} disableTrackOver True to disable mouse tracking. This is only applied at config time. (defaults to false)
  178.      */
  179.     disableTrackOver : false,
  180.     /**
  181.      * @cfg {Boolean} draggable Convenience to initialize drag drop (defaults to false)
  182.      */
  183.     draggable: false,
  184.     /**
  185.      * @cfg {Number} duration Animation duration if animate = true (defaults to 0.35)
  186.      */
  187.     duration : 0.35,
  188.     /**
  189.      * @cfg {Boolean} dynamic True to resize the element while dragging instead of using a proxy (defaults to false)
  190.      */
  191.     dynamic : false,
  192.     /**
  193.      * @cfg {String} easing Animation easing if animate = true (defaults to <tt>'easingOutStrong'</tt>)
  194.      */
  195.     easing : 'easeOutStrong',
  196.     /**
  197.      * @cfg {Boolean} enabled False to disable resizing (defaults to true)
  198.      */
  199.     enabled : true,
  200.     /**
  201.      * @property enabled Writable. False if resizing is disabled.
  202.      * @type Boolean 
  203.      */
  204.     /**
  205.      * @cfg {String} handles String consisting of the resize handles to display (defaults to undefined).
  206.      * Specify either <tt>'all'</tt> or any of <tt>'n s e w ne nw se sw'</tt>.
  207.      */
  208.     handles : false,
  209.     /**
  210.      * @cfg {Boolean} multiDirectional <b>Deprecated</b>.  Deprecated style of adding multi-direction resize handles.
  211.      */
  212.     multiDirectional : false,
  213.     /**
  214.      * @cfg {Number} height The height of the element in pixels (defaults to null)
  215.      */
  216.     height : null,
  217.     /**
  218.      * @cfg {Number} width The width of the element in pixels (defaults to null)
  219.      */
  220.     width : null,
  221.     /**
  222.      * @cfg {Number} heightIncrement The increment to snap the height resize in pixels
  223.      * (only applies if <code>{@link #dynamic}==true</code>). Defaults to <tt>0</tt>.
  224.      */
  225.     heightIncrement : 0,
  226.     /**
  227.      * @cfg {Number} widthIncrement The increment to snap the width resize in pixels
  228.      * (only applies if <code>{@link #dynamic}==true</code>). Defaults to <tt>0</tt>.
  229.      */
  230.     widthIncrement : 0,
  231.     /**
  232.      * @cfg {Number} minHeight The minimum height for the element (defaults to 5)
  233.      */
  234.     minHeight : 5,
  235.     /**
  236.      * @cfg {Number} minWidth The minimum width for the element (defaults to 5)
  237.      */
  238.     minWidth : 5,
  239.     /**
  240.      * @cfg {Number} maxHeight The maximum height for the element (defaults to 10000)
  241.      */
  242.     maxHeight : 10000,
  243.     /**
  244.      * @cfg {Number} maxWidth The maximum width for the element (defaults to 10000)
  245.      */
  246.     maxWidth : 10000,
  247.     /**
  248.      * @cfg {Number} minX The minimum x for the element (defaults to 0)
  249.      */
  250.     minX: 0,
  251.     /**
  252.      * @cfg {Number} minY The minimum x for the element (defaults to 0)
  253.      */
  254.     minY: 0,
  255.     /**
  256.      * @cfg {Boolean} pinned True to ensure that the resize handles are always visible, false to display them only when the
  257.      * user mouses over the resizable borders. This is only applied at config time. (defaults to false)
  258.      */
  259.     pinned : false,
  260.     /**
  261.      * @cfg {Boolean} preserveRatio True to preserve the original ratio between height
  262.      * and width during resize (defaults to false)
  263.      */
  264.     preserveRatio : false,
  265.     /**
  266.      * @cfg {Boolean/String/Element} resizeChild True to resize the first child, or id/element to resize (defaults to false) 
  267.      */ 
  268.     resizeChild : false,
  269.     /**
  270.      * @cfg {Boolean} transparent True for transparent handles. This is only applied at config time. (defaults to false)
  271.      */
  272.     transparent: false,
  273.     /**
  274.      * @cfg {Ext.lib.Region} resizeRegion Constrain the resize to a particular region
  275.      */
  276.     /**
  277.      * @cfg {Boolean} wrap True to wrap an element with a div if needed (required for textareas and images, defaults to false)
  278.      * in favor of the handles config option (defaults to false)
  279.      */
  280.     
  281.     /**
  282.      * Perform a manual resize and fires the 'resize' event.
  283.      * @param {Number} width
  284.      * @param {Number} height
  285.      */
  286.     resizeTo : function(width, height){
  287.         this.el.setSize(width, height);
  288.         this.updateChildSize();
  289.         this.fireEvent('resize', this, width, height, null);
  290.     },
  291.     // private
  292.     startSizing : function(e, handle){
  293.         this.fireEvent('beforeresize', this, e);
  294.         if(this.enabled){ // 2nd enabled check in case disabled before beforeresize handler
  295.             if(!this.overlay){
  296.                 this.overlay = this.el.createProxy({tag: 'div', cls: 'x-resizable-overlay', html: '&#160;'}, Ext.getBody());
  297.                 this.overlay.unselectable();
  298.                 this.overlay.enableDisplayMode('block');
  299.                 this.overlay.on({
  300.                     scope: this,
  301.                     mousemove: this.onMouseMove,
  302.                     mouseup: this.onMouseUp
  303.                 });
  304.             }
  305.             this.overlay.setStyle('cursor', handle.el.getStyle('cursor'));
  306.             this.resizing = true;
  307.             this.startBox = this.el.getBox();
  308.             this.startPoint = e.getXY();
  309.             this.offsets = [(this.startBox.x + this.startBox.width) - this.startPoint[0],
  310.                             (this.startBox.y + this.startBox.height) - this.startPoint[1]];
  311.             this.overlay.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
  312.             this.overlay.show();
  313.             if(this.constrainTo) {
  314.                 var ct = Ext.get(this.constrainTo);
  315.                 this.resizeRegion = ct.getRegion().adjust(
  316.                     ct.getFrameWidth('t'),
  317.                     ct.getFrameWidth('l'),
  318.                     -ct.getFrameWidth('b'),
  319.                     -ct.getFrameWidth('r')
  320.                 );
  321.             }
  322.             this.proxy.setStyle('visibility', 'hidden'); // workaround display none
  323.             this.proxy.show();
  324.             this.proxy.setBox(this.startBox);
  325.             if(!this.dynamic){
  326.                 this.proxy.setStyle('visibility', 'visible');
  327.             }
  328.         }
  329.     },
  330.     // private
  331.     onMouseDown : function(handle, e){
  332.         if(this.enabled){
  333.             e.stopEvent();
  334.             this.activeHandle = handle;
  335.             this.startSizing(e, handle);
  336.         }          
  337.     },
  338.     // private
  339.     onMouseUp : function(e){
  340.         this.activeHandle = null;
  341.         var size = this.resizeElement();
  342.         this.resizing = false;
  343.         this.handleOut();
  344.         this.overlay.hide();
  345.         this.proxy.hide();
  346.         this.fireEvent('resize', this, size.width, size.height, e);
  347.     },
  348.     // private
  349.     updateChildSize : function(){
  350.         if(this.resizeChild){
  351.             var el = this.el;
  352.             var child = this.resizeChild;
  353.             var adj = this.adjustments;
  354.             if(el.dom.offsetWidth){
  355.                 var b = el.getSize(true);
  356.                 child.setSize(b.width+adj[0], b.height+adj[1]);
  357.             }
  358.             // Second call here for IE
  359.             // The first call enables instant resizing and
  360.             // the second call corrects scroll bars if they
  361.             // exist
  362.             if(Ext.isIE){
  363.                 setTimeout(function(){
  364.                     if(el.dom.offsetWidth){
  365.                         var b = el.getSize(true);
  366.                         child.setSize(b.width+adj[0], b.height+adj[1]);
  367.                     }
  368.                 }, 10);
  369.             }
  370.         }
  371.     },
  372.     // private
  373.     snap : function(value, inc, min){
  374.         if(!inc || !value){
  375.             return value;
  376.         }
  377.         var newValue = value;
  378.         var m = value % inc;
  379.         if(m > 0){
  380.             if(m > (inc/2)){
  381.                 newValue = value + (inc-m);
  382.             }else{
  383.                 newValue = value - m;
  384.             }
  385.         }
  386.         return Math.max(min, newValue);
  387.     },
  388.     /**
  389.      * <p>Performs resizing of the associated Element. This method is called internally by this
  390.      * class, and should not be called by user code.</p>
  391.      * <p>If a Resizable is being used to resize an Element which encapsulates a more complex UI
  392.      * component such as a Panel, this method may be overridden by specifying an implementation
  393.      * as a config option to provide appropriate behaviour at the end of the resize operation on
  394.      * mouseup, for example resizing the Panel, and relaying the Panel's content.</p>
  395.      * <p>The new area to be resized to is available by examining the state of the {@link #proxy}
  396.      * Element. Example:
  397. <pre><code>
  398. new Ext.Panel({
  399.     title: 'Resize me',
  400.     x: 100,
  401.     y: 100,
  402.     renderTo: Ext.getBody(),
  403.     floating: true,
  404.     frame: true,
  405.     width: 400,
  406.     height: 200,
  407.     listeners: {
  408.         render: function(p) {
  409.             new Ext.Resizable(p.getEl(), {
  410.                 handles: 'all',
  411.                 pinned: true,
  412.                 transparent: true,
  413.                 resizeElement: function() {
  414.                     var box = this.proxy.getBox();
  415.                     p.updateBox(box);
  416.                     if (p.layout) {
  417.                         p.doLayout();
  418.                     }
  419.                     return box;
  420.                 }
  421.            });
  422.        }
  423.     }
  424. }).show();
  425. </code></pre>
  426.      */
  427.     resizeElement : function(){
  428.         var box = this.proxy.getBox();
  429.         if(this.updateBox){
  430.             this.el.setBox(box, false, this.animate, this.duration, null, this.easing);
  431.         }else{
  432.             this.el.setSize(box.width, box.height, this.animate, this.duration, null, this.easing);
  433.         }
  434.         this.updateChildSize();
  435.         if(!this.dynamic){
  436.             this.proxy.hide();
  437.         }
  438.         return box;
  439.     },
  440.     // private
  441.     constrain : function(v, diff, m, mx){
  442.         if(v - diff < m){
  443.             diff = v - m;    
  444.         }else if(v - diff > mx){
  445.             diff = v - mx; 
  446.         }
  447.         return diff;                
  448.     },
  449.     // private
  450.     onMouseMove : function(e){
  451.         if(this.enabled && this.activeHandle){
  452.             try{// try catch so if something goes wrong the user doesn't get hung
  453.             if(this.resizeRegion && !this.resizeRegion.contains(e.getPoint())) {
  454.                 return;
  455.             }
  456.             //var curXY = this.startPoint;
  457.             var curSize = this.curSize || this.startBox,
  458.                 x = this.startBox.x, y = this.startBox.y,
  459.                 ox = x, 
  460.                 oy = y,
  461.                 w = curSize.width, 
  462.                 h = curSize.height,
  463.                 ow = w, 
  464.                 oh = h,
  465.                 mw = this.minWidth, 
  466.                 mh = this.minHeight,
  467.                 mxw = this.maxWidth, 
  468.                 mxh = this.maxHeight,
  469.                 wi = this.widthIncrement,
  470.                 hi = this.heightIncrement,
  471.                 eventXY = e.getXY(),
  472.                 diffX = -(this.startPoint[0] - Math.max(this.minX, eventXY[0])),
  473.                 diffY = -(this.startPoint[1] - Math.max(this.minY, eventXY[1])),
  474.                 pos = this.activeHandle.position,
  475.                 tw,
  476.                 th;
  477.             
  478.             switch(pos){
  479.                 case 'east':
  480.                     w += diffX; 
  481.                     w = Math.min(Math.max(mw, w), mxw);
  482.                     break;
  483.                 case 'south':
  484.                     h += diffY;
  485.                     h = Math.min(Math.max(mh, h), mxh);
  486.                     break;
  487.                 case 'southeast':
  488.                     w += diffX; 
  489.                     h += diffY;
  490.                     w = Math.min(Math.max(mw, w), mxw);
  491.                     h = Math.min(Math.max(mh, h), mxh);
  492.                     break;
  493.                 case 'north':
  494.                     diffY = this.constrain(h, diffY, mh, mxh);
  495.                     y += diffY;
  496.                     h -= diffY;
  497.                     break;
  498.                 case 'west':
  499.                     diffX = this.constrain(w, diffX, mw, mxw);
  500.                     x += diffX;
  501.                     w -= diffX;
  502.                     break;
  503.                 case 'northeast':
  504.                     w += diffX; 
  505.                     w = Math.min(Math.max(mw, w), mxw);
  506.                     diffY = this.constrain(h, diffY, mh, mxh);
  507.                     y += diffY;
  508.                     h -= diffY;
  509.                     break;
  510.                 case 'northwest':
  511.                     diffX = this.constrain(w, diffX, mw, mxw);
  512.                     diffY = this.constrain(h, diffY, mh, mxh);
  513.                     y += diffY;
  514.                     h -= diffY;
  515.                     x += diffX;
  516.                     w -= diffX;
  517.                     break;
  518.                case 'southwest':
  519.                     diffX = this.constrain(w, diffX, mw, mxw);
  520.                     h += diffY;
  521.                     h = Math.min(Math.max(mh, h), mxh);
  522.                     x += diffX;
  523.                     w -= diffX;
  524.                     break;
  525.             }
  526.             
  527.             var sw = this.snap(w, wi, mw);
  528.             var sh = this.snap(h, hi, mh);
  529.             if(sw != w || sh != h){
  530.                 switch(pos){
  531.                     case 'northeast':
  532.                         y -= sh - h;
  533.                     break;
  534.                     case 'north':
  535.                         y -= sh - h;
  536.                         break;
  537.                     case 'southwest':
  538.                         x -= sw - w;
  539.                     break;
  540.                     case 'west':
  541.                         x -= sw - w;
  542.                         break;
  543.                     case 'northwest':
  544.                         x -= sw - w;
  545.                         y -= sh - h;
  546.                     break;
  547.                 }
  548.                 w = sw;
  549.                 h = sh;
  550.             }
  551.             
  552.             if(this.preserveRatio){
  553.                 switch(pos){
  554.                     case 'southeast':
  555.                     case 'east':
  556.                         h = oh * (w/ow);
  557.                         h = Math.min(Math.max(mh, h), mxh);
  558.                         w = ow * (h/oh);
  559.                        break;
  560.                     case 'south':
  561.                         w = ow * (h/oh);
  562.                         w = Math.min(Math.max(mw, w), mxw);
  563.                         h = oh * (w/ow);
  564.                         break;
  565.                     case 'northeast':
  566.                         w = ow * (h/oh);
  567.                         w = Math.min(Math.max(mw, w), mxw);
  568.                         h = oh * (w/ow);
  569.                     break;
  570.                     case 'north':
  571.                         tw = w;
  572.                         w = ow * (h/oh);
  573.                         w = Math.min(Math.max(mw, w), mxw);
  574.                         h = oh * (w/ow);
  575.                         x += (tw - w) / 2;
  576.                         break;
  577.                     case 'southwest':
  578.                         h = oh * (w/ow);
  579.                         h = Math.min(Math.max(mh, h), mxh);
  580.                         tw = w;
  581.                         w = ow * (h/oh);
  582.                         x += tw - w;
  583.                         break;
  584.                     case 'west':
  585.                         th = h;
  586.                         h = oh * (w/ow);
  587.                         h = Math.min(Math.max(mh, h), mxh);
  588.                         y += (th - h) / 2;
  589.                         tw = w;
  590.                         w = ow * (h/oh);
  591.                         x += tw - w;
  592.                        break;
  593.                     case 'northwest':
  594.                         tw = w;
  595.                         th = h;
  596.                         h = oh * (w/ow);
  597.                         h = Math.min(Math.max(mh, h), mxh);
  598.                         w = ow * (h/oh);
  599.                         y += th - h;
  600.                         x += tw - w;
  601.                         break;
  602.                         
  603.                 }
  604.             }
  605.             this.proxy.setBounds(x, y, w, h);
  606.             if(this.dynamic){
  607.                 this.resizeElement();
  608.             }
  609.             }catch(ex){}
  610.         }
  611.     },
  612.     // private
  613.     handleOver : function(){
  614.         if(this.enabled){
  615.             this.el.addClass('x-resizable-over');
  616.         }
  617.     },
  618.     // private
  619.     handleOut : function(){
  620.         if(!this.resizing){
  621.             this.el.removeClass('x-resizable-over');
  622.         }
  623.     },
  624.     
  625.     /**
  626.      * Returns the element this component is bound to.
  627.      * @return {Ext.Element}
  628.      */
  629.     getEl : function(){
  630.         return this.el;
  631.     },
  632.     
  633.     /**
  634.      * Returns the resizeChild element (or null).
  635.      * @return {Ext.Element}
  636.      */
  637.     getResizeChild : function(){
  638.         return this.resizeChild;
  639.     },
  640.     
  641.     /**
  642.      * Destroys this resizable. If the element was wrapped and 
  643.      * removeEl is not true then the element remains.
  644.      * @param {Boolean} removeEl (optional) true to remove the element from the DOM
  645.      */
  646.     destroy : function(removeEl){
  647.         Ext.destroy(this.dd, this.overlay, this.proxy);
  648.         this.overlay = null;
  649.         this.proxy = null;
  650.         
  651.         var ps = Ext.Resizable.positions;
  652.         for(var k in ps){
  653.             if(typeof ps[k] != 'function' && this[ps[k]]){
  654.                 this[ps[k]].destroy();
  655.             }
  656.         }
  657.         if(removeEl){
  658.             this.el.update('');
  659.             Ext.destroy(this.el);
  660.             this.el = null;
  661.         }
  662.         this.purgeListeners();
  663.     },
  664.     syncHandleHeight : function(){
  665.         var h = this.el.getHeight(true);
  666.         if(this.west){
  667.             this.west.el.setHeight(h);
  668.         }
  669.         if(this.east){
  670.             this.east.el.setHeight(h);
  671.         }
  672.     }
  673. });
  674. // private
  675. // hash to map config positions to true positions
  676. Ext.Resizable.positions = {
  677.     n: 'north', s: 'south', e: 'east', w: 'west', se: 'southeast', sw: 'southwest', nw: 'northwest', ne: 'northeast'
  678. };
  679. // private
  680. Ext.Resizable.Handle = function(rz, pos, disableTrackOver, transparent){
  681.     if(!this.tpl){
  682.         // only initialize the template if resizable is used
  683.         var tpl = Ext.DomHelper.createTemplate(
  684.             {tag: 'div', cls: 'x-resizable-handle x-resizable-handle-{0}'}
  685.         );
  686.         tpl.compile();
  687.         Ext.Resizable.Handle.prototype.tpl = tpl;
  688.     }
  689.     this.position = pos;
  690.     this.rz = rz;
  691.     this.el = this.tpl.append(rz.el.dom, [this.position], true);
  692.     this.el.unselectable();
  693.     if(transparent){
  694.         this.el.setOpacity(0);
  695.     }
  696.     this.el.on('mousedown', this.onMouseDown, this);
  697.     if(!disableTrackOver){
  698.         this.el.on({
  699.             scope: this,
  700.             mouseover: this.onMouseOver,
  701.             mouseout: this.onMouseOut
  702.         });
  703.     }
  704. };
  705. // private
  706. Ext.Resizable.Handle.prototype = {
  707.     // private
  708.     afterResize : function(rz){
  709.         // do nothing    
  710.     },
  711.     // private
  712.     onMouseDown : function(e){
  713.         this.rz.onMouseDown(this, e);
  714.     },
  715.     // private
  716.     onMouseOver : function(e){
  717.         this.rz.handleOver(this, e);
  718.     },
  719.     // private
  720.     onMouseOut : function(e){
  721.         this.rz.handleOut(this, e);
  722.     },
  723.     // private
  724.     destroy : function(){
  725.         Ext.destroy(this.el);
  726.         this.el = null;
  727.     }
  728. };