Element.alignment.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.Element
  3.  */
  4. Ext.Element.addMethods({
  5.     /**
  6.      * Gets the x,y coordinates specified by the anchor position on the element.
  7.      * @param {String} anchor (optional) The specified anchor position (defaults to "c").  See {@link #alignTo}
  8.      * for details on supported anchor positions.
  9.      * @param {Boolean} local (optional) True to get the local (element top/left-relative) anchor position instead
  10.      * of page coordinates
  11.      * @param {Object} size (optional) An object containing the size to use for calculating anchor position
  12.      * {width: (target width), height: (target height)} (defaults to the element's current size)
  13.      * @return {Array} [x, y] An array containing the element's x and y coordinates
  14.      */
  15.     getAnchorXY : function(anchor, local, s){
  16.         //Passing a different size is useful for pre-calculating anchors,
  17.         //especially for anchored animations that change the el size.
  18. anchor = (anchor || "tl").toLowerCase();
  19.         s = s || {};
  20.         
  21.         var me = this,        
  22.          vp = me.dom == document.body || me.dom == document,
  23.          w = s.width || vp ? Ext.lib.Dom.getViewWidth() : me.getWidth(),
  24.          h = s.height || vp ? Ext.lib.Dom.getViewHeight() : me.getHeight(),                  
  25.          xy,       
  26.          r = Math.round,
  27.          o = me.getXY(),
  28.          scroll = me.getScroll(),
  29.          extraX = vp ? scroll.left : !local ? o[0] : 0,
  30.          extraY = vp ? scroll.top : !local ? o[1] : 0,
  31.          hash = {
  32.          c  : [r(w * 0.5), r(h * 0.5)],
  33.          t  : [r(w * 0.5), 0],
  34.          l  : [0, r(h * 0.5)],
  35.          r  : [w, r(h * 0.5)],
  36.          b  : [r(w * 0.5), h],
  37.          tl : [0, 0],
  38.          bl : [0, h],
  39.          br : [w, h],
  40.          tr : [w, 0]
  41.          };
  42.         
  43.         xy = hash[anchor];
  44.         return [xy[0] + extraX, xy[1] + extraY]; 
  45.     },
  46.     /**
  47.      * Anchors an element to another element and realigns it when the window is resized.
  48.      * @param {Mixed} element The element to align to.
  49.      * @param {String} position The position to align to.
  50.      * @param {Array} offsets (optional) Offset the positioning by [x, y]
  51.      * @param {Boolean/Object} animate (optional) True for the default animation or a standard Element animation config object
  52.      * @param {Boolean/Number} monitorScroll (optional) True to monitor body scroll and reposition. If this parameter
  53.      * is a number, it is used as the buffer delay (defaults to 50ms).
  54.      * @param {Function} callback The function to call after the animation finishes
  55.      * @return {Ext.Element} this
  56.      */
  57.     anchorTo : function(el, alignment, offsets, animate, monitorScroll, callback){        
  58.     var me = this,
  59.             dom = me.dom;
  60.     
  61.     function action(){
  62.             Ext.fly(dom).alignTo(el, alignment, offsets, animate);
  63.             Ext.callback(callback, Ext.fly(dom));
  64.         }
  65.         
  66.         Ext.EventManager.onWindowResize(action, me);
  67.         
  68.         if(!Ext.isEmpty(monitorScroll)){
  69.             Ext.EventManager.on(window, 'scroll', action, me,
  70.                 {buffer: !isNaN(monitorScroll) ? monitorScroll : 50});
  71.         }
  72.         action.call(me); // align immediately
  73.         return me;
  74.     },
  75.     /**
  76.      * Gets the x,y coordinates to align this element with another element. See {@link #alignTo} for more info on the
  77.      * supported position values.
  78.      * @param {Mixed} element The element to align to.
  79.      * @param {String} position The position to align to.
  80.      * @param {Array} offsets (optional) Offset the positioning by [x, y]
  81.      * @return {Array} [x, y]
  82.      */
  83.     getAlignToXY : function(el, p, o){     
  84.         el = Ext.get(el);
  85.         
  86.         if(!el || !el.dom){
  87.             throw "Element.alignToXY with an element that doesn't exist";
  88.         }
  89.         
  90.         o = o || [0,0];
  91.         p = (p == "?" ? "tl-bl?" : (!/-/.test(p) && p !== "" ? "tl-" + p : p || "tl-bl")).toLowerCase();       
  92.                 
  93.         var me = this,
  94.          d = me.dom,
  95.          a1,
  96.          a2,
  97.          x,
  98.          y,
  99.          //constrain the aligned el to viewport if necessary
  100.          w,
  101.          h,
  102.          r,
  103.          dw = Ext.lib.Dom.getViewWidth() -10, // 10px of margin for ie
  104.          dh = Ext.lib.Dom.getViewHeight()-10, // 10px of margin for ie
  105.          p1y,
  106.          p1x,        
  107.          p2y,
  108.          p2x,
  109.          swapY,
  110.          swapX,
  111.          doc = document,
  112.          docElement = doc.documentElement,
  113.          docBody = doc.body,
  114.          scrollX = (docElement.scrollLeft || docBody.scrollLeft || 0)+5,
  115.          scrollY = (docElement.scrollTop || docBody.scrollTop || 0)+5,
  116.          c = false, //constrain to viewport
  117.          p1 = "", 
  118.          p2 = "",
  119.          m = p.match(/^([a-z]+)-([a-z]+)(?)?$/);
  120.         
  121.         if(!m){
  122.            throw "Element.alignTo with an invalid alignment " + p;
  123.         }
  124.         
  125.         p1 = m[1]; 
  126.         p2 = m[2]; 
  127.         c = !!m[3];
  128.         //Subtract the aligned el's internal xy from the target's offset xy
  129.         //plus custom offset to get the aligned el's new offset xy
  130.         a1 = me.getAnchorXY(p1, true);
  131.         a2 = el.getAnchorXY(p2, false);
  132.         x = a2[0] - a1[0] + o[0];
  133.         y = a2[1] - a1[1] + o[1];
  134.         if(c){    
  135.        w = me.getWidth();
  136.            h = me.getHeight();
  137.            r = el.getRegion();       
  138.            //If we are at a viewport boundary and the aligned el is anchored on a target border that is
  139.            //perpendicular to the vp border, allow the aligned el to slide on that border,
  140.            //otherwise swap the aligned el to the opposite border of the target.
  141.            p1y = p1.charAt(0);
  142.            p1x = p1.charAt(p1.length-1);
  143.            p2y = p2.charAt(0);
  144.            p2x = p2.charAt(p2.length-1);
  145.            swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));
  146.            swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));          
  147.            
  148.            if (x + w > dw + scrollX) {
  149.                 x = swapX ? r.left-w : dw+scrollX-w;
  150.            }
  151.            if (x < scrollX) {
  152.                x = swapX ? r.right : scrollX;
  153.            }
  154.            if (y + h > dh + scrollY) {
  155.                 y = swapY ? r.top-h : dh+scrollY-h;
  156.             }
  157.            if (y < scrollY){
  158.                y = swapY ? r.bottom : scrollY;
  159.            }
  160.         }
  161.         return [x,y];
  162.     },
  163.     /**
  164.      * Aligns this element with another element relative to the specified anchor points. If the other element is the
  165.      * document it aligns it to the viewport.
  166.      * The position parameter is optional, and can be specified in any one of the following formats:
  167.      * <ul>
  168.      *   <li><b>Blank</b>: Defaults to aligning the element's top-left corner to the target's bottom-left corner ("tl-bl").</li>
  169.      *   <li><b>One anchor (deprecated)</b>: The passed anchor position is used as the target element's anchor point.
  170.      *       The element being aligned will position its top-left corner (tl) to that point.  <i>This method has been
  171.      *       deprecated in favor of the newer two anchor syntax below</i>.</li>
  172.      *   <li><b>Two anchors</b>: If two values from the table below are passed separated by a dash, the first value is used as the
  173.      *       element's anchor point, and the second value is used as the target's anchor point.</li>
  174.      * </ul>
  175.      * In addition to the anchor points, the position parameter also supports the "?" character.  If "?" is passed at the end of
  176.      * the position string, the element will attempt to align as specified, but the position will be adjusted to constrain to
  177.      * the viewport if necessary.  Note that the element being aligned might be swapped to align to a different position than
  178.      * that specified in order to enforce the viewport constraints.
  179.      * Following are all of the supported anchor positions:
  180. <pre>
  181. Value  Description
  182. -----  -----------------------------
  183. tl     The top left corner (default)
  184. t      The center of the top edge
  185. tr     The top right corner
  186. l      The center of the left edge
  187. c      In the center of the element
  188. r      The center of the right edge
  189. bl     The bottom left corner
  190. b      The center of the bottom edge
  191. br     The bottom right corner
  192. </pre>
  193. Example Usage:
  194. <pre><code>
  195. // align el to other-el using the default positioning ("tl-bl", non-constrained)
  196. el.alignTo("other-el");
  197. // align the top left corner of el with the top right corner of other-el (constrained to viewport)
  198. el.alignTo("other-el", "tr?");
  199. // align the bottom right corner of el with the center left edge of other-el
  200. el.alignTo("other-el", "br-l?");
  201. // align the center of el with the bottom left corner of other-el and
  202. // adjust the x position by -6 pixels (and the y position by 0)
  203. el.alignTo("other-el", "c-bl", [-6, 0]);
  204. </code></pre>
  205.      * @param {Mixed} element The element to align to.
  206.      * @param {String} position The position to align to.
  207.      * @param {Array} offsets (optional) Offset the positioning by [x, y]
  208.      * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
  209.      * @return {Ext.Element} this
  210.      */
  211.     alignTo : function(element, position, offsets, animate){
  212.     var me = this;
  213.         return me.setXY(me.getAlignToXY(element, position, offsets),
  214.                    me.preanim && !!animate ? me.preanim(arguments, 3) : false);
  215.     },
  216.     
  217.     // private ==>  used outside of core
  218.     adjustForConstraints : function(xy, parent, offsets){
  219.         return this.getConstrainToXY(parent || document, false, offsets, xy) ||  xy;
  220.     },
  221.     // private ==>  used outside of core
  222.     getConstrainToXY : function(el, local, offsets, proposedXY){   
  223.     var os = {top:0, left:0, bottom:0, right: 0};
  224.         return function(el, local, offsets, proposedXY){
  225.             el = Ext.get(el);
  226.             offsets = offsets ? Ext.applyIf(offsets, os) : os;
  227.             var vw, vh, vx = 0, vy = 0;
  228.             if(el.dom == document.body || el.dom == document){
  229.                 vw =Ext.lib.Dom.getViewWidth();
  230.                 vh = Ext.lib.Dom.getViewHeight();
  231.             }else{
  232.                 vw = el.dom.clientWidth;
  233.                 vh = el.dom.clientHeight;
  234.                 if(!local){
  235.                     var vxy = el.getXY();
  236.                     vx = vxy[0];
  237.                     vy = vxy[1];
  238.                 }
  239.             }
  240.             var s = el.getScroll();
  241.             vx += offsets.left + s.left;
  242.             vy += offsets.top + s.top;
  243.             vw -= offsets.right;
  244.             vh -= offsets.bottom;
  245.             var vr = vx+vw;
  246.             var vb = vy+vh;
  247.             var xy = proposedXY || (!local ? this.getXY() : [this.getLeft(true), this.getTop(true)]);
  248.             var x = xy[0], y = xy[1];
  249.             var w = this.dom.offsetWidth, h = this.dom.offsetHeight;
  250.             // only move it if it needs it
  251.             var moved = false;
  252.             // first validate right/bottom
  253.             if((x + w) > vr){
  254.                 x = vr - w;
  255.                 moved = true;
  256.             }
  257.             if((y + h) > vb){
  258.                 y = vb - h;
  259.                 moved = true;
  260.             }
  261.             // then make sure top/left isn't negative
  262.             if(x < vx){
  263.                 x = vx;
  264.                 moved = true;
  265.             }
  266.             if(y < vy){
  267.                 y = vy;
  268.                 moved = true;
  269.             }
  270.             return moved ? [x, y] : false;
  271.         };
  272.     }(),
  273.     
  274.     
  275.         
  276. //         el = Ext.get(el);
  277. //         offsets = Ext.applyIf(offsets || {}, {top : 0, left : 0, bottom : 0, right : 0});
  278. //         var me = this,
  279. //          doc = document,
  280. //          s = el.getScroll(),
  281. //          vxy = el.getXY(),
  282. //          vx = offsets.left + s.left, 
  283. //          vy = offsets.top + s.top,            
  284. //          vw = -offsets.right, 
  285. //          vh = -offsets.bottom, 
  286. //          vr,
  287. //          vb,
  288. //          xy = proposedXY || (!local ? me.getXY() : [me.getLeft(true), me.getTop(true)]),
  289. //          x = xy[0],
  290. //          y = xy[1],
  291. //          w = me.dom.offsetWidth, h = me.dom.offsetHeight,
  292. //          moved = false; // only move it if it needs it
  293. //       
  294. //         
  295. //         if(el.dom == doc.body || el.dom == doc){
  296. //             vw += Ext.lib.Dom.getViewWidth();
  297. //             vh += Ext.lib.Dom.getViewHeight();
  298. //         }else{
  299. //             vw += el.dom.clientWidth;
  300. //             vh += el.dom.clientHeight;
  301. //             if(!local){                    
  302. //                 vx += vxy[0];
  303. //                 vy += vxy[1];
  304. //             }
  305. //         }
  306. //         // first validate right/bottom
  307. //         if(x + w > vx + vw){
  308. //             x = vx + vw - w;
  309. //             moved = true;
  310. //         }
  311. //         if(y + h > vy + vh){
  312. //             y = vy + vh - h;
  313. //             moved = true;
  314. //         }
  315. //         // then make sure top/left isn't negative
  316. //         if(x < vx){
  317. //             x = vx;
  318. //             moved = true;
  319. //         }
  320. //         if(y < vy){
  321. //             y = vy;
  322. //             moved = true;
  323. //         }
  324. //         return moved ? [x, y] : false;
  325. //    },
  326.     
  327.     /**
  328.     * Calculates the x, y to center this element on the screen
  329.     * @return {Array} The x, y values [x, y]
  330.     */
  331.     getCenterXY : function(){
  332.         return this.getAlignToXY(document, 'c-c');
  333.     },
  334.     /**
  335.     * Centers the Element in either the viewport, or another Element.
  336.     * @param {Mixed} centerIn (optional) The element in which to center the element.
  337.     */
  338.     center : function(centerIn){
  339.         return this.alignTo(centerIn || document, 'c-c');        
  340.     }    
  341. });