Resizable.js
上传用户:dawnssy
上传日期:2022-08-06
资源大小:9345k
文件大小:25k
源码类别:

JavaScript

开发平台:

JavaScript

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