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

中间件编程

开发平台:

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.SplitBar
  3.  * @extends Ext.util.Observable
  4.  * Creates draggable splitter bar functionality from two elements (element to be dragged and element to be resized).
  5.  * <br><br>
  6.  * Usage:
  7.  * <pre><code>
  8. var split = new Ext.SplitBar("elementToDrag", "elementToSize",
  9.                    Ext.SplitBar.HORIZONTAL, Ext.SplitBar.LEFT);
  10. split.setAdapter(new Ext.SplitBar.AbsoluteLayoutAdapter("container"));
  11. split.minSize = 100;
  12. split.maxSize = 600;
  13. split.animate = true;
  14. split.on('moved', splitterMoved);
  15. </code></pre>
  16.  * @constructor
  17.  * Create a new SplitBar
  18.  * @param {Mixed} dragElement The element to be dragged and act as the SplitBar.
  19.  * @param {Mixed} resizingElement The element to be resized based on where the SplitBar element is dragged
  20.  * @param {Number} orientation (optional) Either Ext.SplitBar.HORIZONTAL or Ext.SplitBar.VERTICAL. (Defaults to HORIZONTAL)
  21.  * @param {Number} placement (optional) Either Ext.SplitBar.LEFT or Ext.SplitBar.RIGHT for horizontal or  
  22.                         Ext.SplitBar.TOP or Ext.SplitBar.BOTTOM for vertical. (By default, this is determined automatically by the initial
  23.                         position of the SplitBar).
  24.  */
  25. Ext.SplitBar = function(dragElement, resizingElement, orientation, placement, existingProxy){
  26.     
  27.     /** @private */
  28.     this.el = Ext.get(dragElement, true);
  29.     this.el.dom.unselectable = "on";
  30.     /** @private */
  31.     this.resizingEl = Ext.get(resizingElement, true);
  32.     /**
  33.      * @private
  34.      * The orientation of the split. Either Ext.SplitBar.HORIZONTAL or Ext.SplitBar.VERTICAL. (Defaults to HORIZONTAL)
  35.      * Note: If this is changed after creating the SplitBar, the placement property must be manually updated
  36.      * @type Number
  37.      */
  38.     this.orientation = orientation || Ext.SplitBar.HORIZONTAL;
  39.     
  40.     /**
  41.      * The increment, in pixels by which to move this SplitBar. When <i>undefined</i>, the SplitBar moves smoothly.
  42.      * @type Number
  43.      * @property tickSize
  44.      */
  45.     /**
  46.      * The minimum size of the resizing element. (Defaults to 0)
  47.      * @type Number
  48.      */
  49.     this.minSize = 0;
  50.     
  51.     /**
  52.      * The maximum size of the resizing element. (Defaults to 2000)
  53.      * @type Number
  54.      */
  55.     this.maxSize = 2000;
  56.     
  57.     /**
  58.      * Whether to animate the transition to the new size
  59.      * @type Boolean
  60.      */
  61.     this.animate = false;
  62.     
  63.     /**
  64.      * Whether to create a transparent shim that overlays the page when dragging, enables dragging across iframes.
  65.      * @type Boolean
  66.      */
  67.     this.useShim = false;
  68.     
  69.     /** @private */
  70.     this.shim = null;
  71.     
  72.     if(!existingProxy){
  73.         /** @private */
  74.         this.proxy = Ext.SplitBar.createProxy(this.orientation);
  75.     }else{
  76.         this.proxy = Ext.get(existingProxy).dom;
  77.     }
  78.     /** @private */
  79.     this.dd = new Ext.dd.DDProxy(this.el.dom.id, "XSplitBars", {dragElId : this.proxy.id});
  80.     
  81.     /** @private */
  82.     this.dd.b4StartDrag = this.onStartProxyDrag.createDelegate(this);
  83.     
  84.     /** @private */
  85.     this.dd.endDrag = this.onEndProxyDrag.createDelegate(this);
  86.     
  87.     /** @private */
  88.     this.dragSpecs = {};
  89.     
  90.     /**
  91.      * @private The adapter to use to positon and resize elements
  92.      */
  93.     this.adapter = new Ext.SplitBar.BasicLayoutAdapter();
  94.     this.adapter.init(this);
  95.     
  96.     if(this.orientation == Ext.SplitBar.HORIZONTAL){
  97.         /** @private */
  98.         this.placement = placement || (this.el.getX() > this.resizingEl.getX() ? Ext.SplitBar.LEFT : Ext.SplitBar.RIGHT);
  99.         this.el.addClass("x-splitbar-h");
  100.     }else{
  101.         /** @private */
  102.         this.placement = placement || (this.el.getY() > this.resizingEl.getY() ? Ext.SplitBar.TOP : Ext.SplitBar.BOTTOM);
  103.         this.el.addClass("x-splitbar-v");
  104.     }
  105.     
  106.     this.addEvents(
  107.         /**
  108.          * @event resize
  109.          * Fires when the splitter is moved (alias for {@link #moved})
  110.          * @param {Ext.SplitBar} this
  111.          * @param {Number} newSize the new width or height
  112.          */
  113.         "resize",
  114.         /**
  115.          * @event moved
  116.          * Fires when the splitter is moved
  117.          * @param {Ext.SplitBar} this
  118.          * @param {Number} newSize the new width or height
  119.          */
  120.         "moved",
  121.         /**
  122.          * @event beforeresize
  123.          * Fires before the splitter is dragged
  124.          * @param {Ext.SplitBar} this
  125.          */
  126.         "beforeresize",
  127.         "beforeapply"
  128.     );
  129.     Ext.SplitBar.superclass.constructor.call(this);
  130. };
  131. Ext.extend(Ext.SplitBar, Ext.util.Observable, {
  132.     onStartProxyDrag : function(x, y){
  133.         this.fireEvent("beforeresize", this);
  134.         this.overlay =  Ext.DomHelper.append(document.body,  {cls: "x-drag-overlay", html: "&#160;"}, true);
  135.         this.overlay.unselectable();
  136.         this.overlay.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
  137.         this.overlay.show();
  138.         Ext.get(this.proxy).setDisplayed("block");
  139.         var size = this.adapter.getElementSize(this);
  140.         this.activeMinSize = this.getMinimumSize();
  141.         this.activeMaxSize = this.getMaximumSize();
  142.         var c1 = size - this.activeMinSize;
  143.         var c2 = Math.max(this.activeMaxSize - size, 0);
  144.         if(this.orientation == Ext.SplitBar.HORIZONTAL){
  145.             this.dd.resetConstraints();
  146.             this.dd.setXConstraint(
  147.                 this.placement == Ext.SplitBar.LEFT ? c1 : c2, 
  148.                 this.placement == Ext.SplitBar.LEFT ? c2 : c1,
  149.                 this.tickSize
  150.             );
  151.             this.dd.setYConstraint(0, 0);
  152.         }else{
  153.             this.dd.resetConstraints();
  154.             this.dd.setXConstraint(0, 0);
  155.             this.dd.setYConstraint(
  156.                 this.placement == Ext.SplitBar.TOP ? c1 : c2, 
  157.                 this.placement == Ext.SplitBar.TOP ? c2 : c1,
  158.                 this.tickSize
  159.             );
  160.          }
  161.         this.dragSpecs.startSize = size;
  162.         this.dragSpecs.startPoint = [x, y];
  163.         Ext.dd.DDProxy.prototype.b4StartDrag.call(this.dd, x, y);
  164.     },
  165.     
  166.     /** 
  167.      * @private Called after the drag operation by the DDProxy
  168.      */
  169.     onEndProxyDrag : function(e){
  170.         Ext.get(this.proxy).setDisplayed(false);
  171.         var endPoint = Ext.lib.Event.getXY(e);
  172.         if(this.overlay){
  173.             Ext.destroy(this.overlay);
  174.             delete this.overlay;
  175.         }
  176.         var newSize;
  177.         if(this.orientation == Ext.SplitBar.HORIZONTAL){
  178.             newSize = this.dragSpecs.startSize + 
  179.                 (this.placement == Ext.SplitBar.LEFT ?
  180.                     endPoint[0] - this.dragSpecs.startPoint[0] :
  181.                     this.dragSpecs.startPoint[0] - endPoint[0]
  182.                 );
  183.         }else{
  184.             newSize = this.dragSpecs.startSize + 
  185.                 (this.placement == Ext.SplitBar.TOP ?
  186.                     endPoint[1] - this.dragSpecs.startPoint[1] :
  187.                     this.dragSpecs.startPoint[1] - endPoint[1]
  188.                 );
  189.         }
  190.         newSize = Math.min(Math.max(newSize, this.activeMinSize), this.activeMaxSize);
  191.         if(newSize != this.dragSpecs.startSize){
  192.             if(this.fireEvent('beforeapply', this, newSize) !== false){
  193.                 this.adapter.setElementSize(this, newSize);
  194.                 this.fireEvent("moved", this, newSize);
  195.                 this.fireEvent("resize", this, newSize);
  196.             }
  197.         }
  198.     },
  199.     
  200.     /**
  201.      * Get the adapter this SplitBar uses
  202.      * @return The adapter object
  203.      */
  204.     getAdapter : function(){
  205.         return this.adapter;
  206.     },
  207.     
  208.     /**
  209.      * Set the adapter this SplitBar uses
  210.      * @param {Object} adapter A SplitBar adapter object
  211.      */
  212.     setAdapter : function(adapter){
  213.         this.adapter = adapter;
  214.         this.adapter.init(this);
  215.     },
  216.     
  217.     /**
  218.      * Gets the minimum size for the resizing element
  219.      * @return {Number} The minimum size
  220.      */
  221.     getMinimumSize : function(){
  222.         return this.minSize;
  223.     },
  224.     
  225.     /**
  226.      * Sets the minimum size for the resizing element
  227.      * @param {Number} minSize The minimum size
  228.      */
  229.     setMinimumSize : function(minSize){
  230.         this.minSize = minSize;
  231.     },
  232.     
  233.     /**
  234.      * Gets the maximum size for the resizing element
  235.      * @return {Number} The maximum size
  236.      */
  237.     getMaximumSize : function(){
  238.         return this.maxSize;
  239.     },
  240.     
  241.     /**
  242.      * Sets the maximum size for the resizing element
  243.      * @param {Number} maxSize The maximum size
  244.      */
  245.     setMaximumSize : function(maxSize){
  246.         this.maxSize = maxSize;
  247.     },
  248.     
  249.     /**
  250.      * Sets the initialize size for the resizing element
  251.      * @param {Number} size The initial size
  252.      */
  253.     setCurrentSize : function(size){
  254.         var oldAnimate = this.animate;
  255.         this.animate = false;
  256.         this.adapter.setElementSize(this, size);
  257.         this.animate = oldAnimate;
  258.     },
  259.     
  260.     /**
  261.      * Destroy this splitbar. 
  262.      * @param {Boolean} removeEl True to remove the element
  263.      */
  264.     destroy : function(removeEl){
  265. Ext.destroy(this.shim, Ext.get(this.proxy));
  266.         this.dd.unreg();
  267.         if(removeEl){
  268.             this.el.remove();
  269.         }
  270. this.purgeListeners();
  271.     }
  272. });
  273. /**
  274.  * @private static Create our own proxy element element. So it will be the same same size on all browsers, we won't use borders. Instead we use a background color.
  275.  */
  276. Ext.SplitBar.createProxy = function(dir){
  277.     var proxy = new Ext.Element(document.createElement("div"));
  278.     proxy.unselectable();
  279.     var cls = 'x-splitbar-proxy';
  280.     proxy.addClass(cls + ' ' + (dir == Ext.SplitBar.HORIZONTAL ? cls +'-h' : cls + '-v'));
  281.     document.body.appendChild(proxy.dom);
  282.     return proxy.dom;
  283. };
  284. /** 
  285.  * @class Ext.SplitBar.BasicLayoutAdapter
  286.  * Default Adapter. It assumes the splitter and resizing element are not positioned
  287.  * elements and only gets/sets the width of the element. Generally used for table based layouts.
  288.  */
  289. Ext.SplitBar.BasicLayoutAdapter = function(){
  290. };
  291. Ext.SplitBar.BasicLayoutAdapter.prototype = {
  292.     // do nothing for now
  293.     init : function(s){
  294.     
  295.     },
  296.     /**
  297.      * Called before drag operations to get the current size of the resizing element. 
  298.      * @param {Ext.SplitBar} s The SplitBar using this adapter
  299.      */
  300.      getElementSize : function(s){
  301.         if(s.orientation == Ext.SplitBar.HORIZONTAL){
  302.             return s.resizingEl.getWidth();
  303.         }else{
  304.             return s.resizingEl.getHeight();
  305.         }
  306.     },
  307.     
  308.     /**
  309.      * Called after drag operations to set the size of the resizing element.
  310.      * @param {Ext.SplitBar} s The SplitBar using this adapter
  311.      * @param {Number} newSize The new size to set
  312.      * @param {Function} onComplete A function to be invoked when resizing is complete
  313.      */
  314.     setElementSize : function(s, newSize, onComplete){
  315.         if(s.orientation == Ext.SplitBar.HORIZONTAL){
  316.             if(!s.animate){
  317.                 s.resizingEl.setWidth(newSize);
  318.                 if(onComplete){
  319.                     onComplete(s, newSize);
  320.                 }
  321.             }else{
  322.                 s.resizingEl.setWidth(newSize, true, .1, onComplete, 'easeOut');
  323.             }
  324.         }else{
  325.             
  326.             if(!s.animate){
  327.                 s.resizingEl.setHeight(newSize);
  328.                 if(onComplete){
  329.                     onComplete(s, newSize);
  330.                 }
  331.             }else{
  332.                 s.resizingEl.setHeight(newSize, true, .1, onComplete, 'easeOut');
  333.             }
  334.         }
  335.     }
  336. };
  337. /** 
  338.  *@class Ext.SplitBar.AbsoluteLayoutAdapter
  339.  * @extends Ext.SplitBar.BasicLayoutAdapter
  340.  * Adapter that  moves the splitter element to align with the resized sizing element. 
  341.  * Used with an absolute positioned SplitBar.
  342.  * @param {Mixed} container The container that wraps around the absolute positioned content. If it's
  343.  * document.body, make sure you assign an id to the body element.
  344.  */
  345. Ext.SplitBar.AbsoluteLayoutAdapter = function(container){
  346.     this.basic = new Ext.SplitBar.BasicLayoutAdapter();
  347.     this.container = Ext.get(container);
  348. };
  349. Ext.SplitBar.AbsoluteLayoutAdapter.prototype = {
  350.     init : function(s){
  351.         this.basic.init(s);
  352.     },
  353.     
  354.     getElementSize : function(s){
  355.         return this.basic.getElementSize(s);
  356.     },
  357.     
  358.     setElementSize : function(s, newSize, onComplete){
  359.         this.basic.setElementSize(s, newSize, this.moveSplitter.createDelegate(this, [s]));
  360.     },
  361.     
  362.     moveSplitter : function(s){
  363.         var yes = Ext.SplitBar;
  364.         switch(s.placement){
  365.             case yes.LEFT:
  366.                 s.el.setX(s.resizingEl.getRight());
  367.                 break;
  368.             case yes.RIGHT:
  369.                 s.el.setStyle("right", (this.container.getWidth() - s.resizingEl.getLeft()) + "px");
  370.                 break;
  371.             case yes.TOP:
  372.                 s.el.setY(s.resizingEl.getBottom());
  373.                 break;
  374.             case yes.BOTTOM:
  375.                 s.el.setY(s.resizingEl.getTop() - s.el.getHeight());
  376.                 break;
  377.         }
  378.     }
  379. };
  380. /**
  381.  * Orientation constant - Create a vertical SplitBar
  382.  * @static
  383.  * @type Number
  384.  */
  385. Ext.SplitBar.VERTICAL = 1;
  386. /**
  387.  * Orientation constant - Create a horizontal SplitBar
  388.  * @static
  389.  * @type Number
  390.  */
  391. Ext.SplitBar.HORIZONTAL = 2;
  392. /**
  393.  * Placement constant - The resizing element is to the left of the splitter element
  394.  * @static
  395.  * @type Number
  396.  */
  397. Ext.SplitBar.LEFT = 1;
  398. /**
  399.  * Placement constant - The resizing element is to the right of the splitter element
  400.  * @static
  401.  * @type Number
  402.  */
  403. Ext.SplitBar.RIGHT = 2;
  404. /**
  405.  * Placement constant - The resizing element is positioned above the splitter element
  406.  * @static
  407.  * @type Number
  408.  */
  409. Ext.SplitBar.TOP = 3;
  410. /**
  411.  * Placement constant - The resizing element is positioned under splitter element
  412.  * @static
  413.  * @type Number
  414.  */
  415. Ext.SplitBar.BOTTOM = 4;