• jquery源码12 offset() : 位置和尺寸的方法


    // Back Compat <1.8 extension point
    jQuery.fx.step = {};
    
    if ( jQuery.expr && jQuery.expr.filters ) {
        jQuery.expr.filters.animated = function( elem ) {
            return jQuery.grep(jQuery.timers, function( fn ) {
                return elem === fn.elem;
            }).length;
        };
    }
    jQuery.fn.offset = function( options ) {
        if ( arguments.length ) {//设置
            return options === undefined ?
                this :
                this.each(function( i ) {//每一个元素设置
                    jQuery.offset.setOffset( this, options, i );
                });
        }
    //获取
        var docElem, win,
            elem = this[ 0 ],
            box = { top: 0, left: 0 },
            doc = elem && elem.ownerDocument;//document
    
        if ( !doc ) {
            return;
        }
    
        docElem = doc.documentElement;//html标签
    
        // Make sure it's not a disconnected DOM node
        if ( !jQuery.contains( docElem, elem ) ) {
            return box;
        }
    
        // getBoundingClientRect()得到一些属性值:ClientRect {top: 8, right: 58, bottom: 58, left: 8,  50…},是到可视区的不包含滚动区域,
        if ( typeof elem.getBoundingClientRect !== core_strundefined ) {
            box = elem.getBoundingClientRect();
        }
        win = getWindow( doc );//获取window
        //pageYOffset是y轴的滚动距离,clientTop边框宽度,
        return {
            top: box.top + win.pageYOffset - docElem.clientTop,
            left: box.left + win.pageXOffset - docElem.clientLeft
        };
    };
    
    jQuery.offset = {
    //设置offset
        setOffset: function( elem, options, i ) {
            var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
                position = jQuery.css( elem, "position" ),//获取元素的position属性,
                curElem = jQuery( elem ),
                props = {};
    
            // Set position first, in-case top/left are set even on static elem
            if ( position === "static" ) {//没有定位就加一个相对定位
                elem.style.position = "relative";
            }
    
            curOffset = curElem.offset();
            curCSSTop = jQuery.css( elem, "top" );
            curCSSLeft = jQuery.css( elem, "left" );
            calculatePosition = ( position === "absolute" || position === "fixed" ) && ( curCSSTop + curCSSLeft ).indexOf("auto") > -1;
    
            // Need to be able to calculate position if either top or left is auto and position is either absolute or fixed
            if ( calculatePosition ) {
                curPosition = curElem.position();
                curTop = curPosition.top;
                curLeft = curPosition.left;
    
            } else {
                curTop = parseFloat( curCSSTop ) || 0;
                curLeft = parseFloat( curCSSLeft ) || 0;
            }
    
            if ( jQuery.isFunction( options ) ) {
                options = options.call( elem, i, curOffset );
            }
    
            if ( options.top != null ) {
                props.top = ( options.top - curOffset.top ) + curTop;
            }
            if ( options.left != null ) {
                props.left = ( options.left - curOffset.left ) + curLeft;
            }
    
            if ( "using" in options ) {
                options.using.call( elem, props );
    
            } else {
                curElem.css( props );
            }
        }
    };
    
    
    jQuery.fn.extend({
    
        position: function() {//获取
            if ( !this[ 0 ] ) {
                return;
            }
    
            var offsetParent, offset,
                elem = this[ 0 ],
                parentOffset = { top: 0, left: 0 };
    
            // Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is it's only offset parent
            if ( jQuery.css( elem, "position" ) === "fixed" ) {
                // We assume that getBoundingClientRect is available when computed position is fixed
                offset = elem.getBoundingClientRect();
    
            } else {
                // 原生方法找父级
                offsetParent = this.offsetParent();
    
                // Get correct offsets
                offset = this.offset();
                if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
                    parentOffset = offsetParent.offset();
                }
    
                // Add offsetParent borders
                parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
                parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
            }
    
            // 自己的top减去父级的top
            return {
                top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
                left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true )
            };
        },
    
        offsetParent: function() {
            return this.map(function() {
                var offsetParent = this.offsetParent || docElem;
    
                while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position") === "static" ) ) {
                    offsetParent = offsetParent.offsetParent;
                }
    
                return offsetParent || docElem;
            });
        }
    });
    
    
    // Create scrollLeft and scrollTop methods
    jQuery.each( {scrollLeft: "pageXOffset", scrollTop: "pageYOffset"}, function( method, prop ) {
        var top = "pageYOffset" === prop;
    
        jQuery.fn[ method ] = function( val ) {
            return jQuery.access( this, function( elem, method, val ) {
                var win = getWindow( elem );
    
                if ( val === undefined ) {
                    return win ? win[ prop ] : elem[ method ];
                }
    
                if ( win ) {
                    win.scrollTo(
                        !top ? val : window.pageXOffset,
                        top ? val : window.pageYOffset
                    );
    
                } else {
                    elem[ method ] = val;//原生的方法
                }
            }, method, val, arguments.length, null );
        };
    });
    
    function getWindow( elem ) {
        return jQuery.isWindow( elem ) ? elem : elem.nodeType === 9 && elem.defaultView;
    }
    // Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
    jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
        jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
            // margin is only for outerHeight, outerWidth
            jQuery.fn[ funcName ] = function( margin, value ) {
                var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
                    extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
    
                return jQuery.access( this, function( elem, type, value ) {
                    var doc;
                    //是window就得到可视区的宽高
                    if ( jQuery.isWindow( elem ) ) {
                        // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
                        // isn't a whole lot we can do. See pull request at this URL for discussion:
                        // https://github.com/jquery/jquery/pull/764
                        return elem.document.documentElement[ "client" + name ];
                    }
    
                    //是document就得到页面的宽高
                    if ( elem.nodeType === 9 ) {
                        doc = elem.documentElement;
    
                        // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],
                        // whichever is greatest
                        return Math.max(
                            elem.body[ "scroll" + name ], doc[ "scroll" + name ],
                            elem.body[ "offset" + name ], doc[ "offset" + name ],
                            doc[ "client" + name ]
                        );
                    }
    
                    return value === undefined ?
                        jQuery.css( elem, type, extra ) ://css方式获取
    
                        jQuery.style( elem, type, value, extra );//style方式获取
                }, type, chainable ? margin : undefined, chainable, null );
            };
        });
    });
    // Limit scope pollution from any deprecated API
    // (function() {
    
    // The number of elements contained in the matched element set
    jQuery.fn.size = function() {
        return this.length;
    };
    
    jQuery.fn.andSelf = jQuery.fn.addBack;
    
    // })();
    if ( typeof module === "object" && module && typeof module.exports === "object" ) {
        // Expose jQuery as module.exports in loaders that implement the Node
        // module pattern (including browserify). Do not create the global, since
        // the user will be storing it themselves locally, and globals are frowned
        // upon in the Node module world.
        module.exports = jQuery;
    } else {
        // Register as a named AMD module, since jQuery can be concatenated with other
        // files that may use define, but not via a proper concatenation script that
        // understands anonymous AMD modules. A named AMD is safest and most robust
        // way to register. Lowercase jquery is used because AMD module names are
        // derived from file names, and jQuery is normally delivered in a lowercase
        // file name. Do this after creating the global so that if an AMD module wants
        // to call noConflict to hide this version of jQuery, it will work.
        if ( typeof define === "function" && define.amd ) {
            define( "jquery", [], function () { return jQuery; } );
        }
    }
    
    // If there is a window object, that at least has a document property,
    // define jQuery and $ identifiers
    if ( typeof window === "object" && typeof window.document === "object" ) {
        window.jQuery = window.$ = jQuery;
    }
    
    })( window );
    <!DOCTYPE HTML>
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>sss</title>
    <script src="jquery-203.js"></script>
    </head>
    <body>
    <script>
    window.onload = function(){
    
        console.log( $('#div1').offset().left );//到屏幕左边的距离。不看父节点有没有定位
        
        console.log( $('#div2').position().left );//到屏幕左边的距离。相对于有定位的父级,不计算margin值
        
        $('#div2').position( {left:100,top:100} );//会自动加一个相对定位
        
        console.log($('#div2').get(0).getBoundingClientRect());//ClientRect {top: 8, right: 58, bottom: 58, left: 8,  50…},是到可视区的不包含滚动区域,
        
    
    }
    </script>
    </head>
    
    <body>
    
    <div id="div1" style="100px;height:100px;background-color:yellow;posotion:relative;">
        <div id='div2' style="50px;height:50px;background-color:red;position:left;left:10;top:10" >
            
        </div>    
    </div>
    </body>
    </html>
  • 相关阅读:
    在django中用MySQL为数据库 新建一个项目的流程
    django ORM中的RelatedManager(关联管理器)
    URL的命名和反向解析
    自定义分页的插件
    从数据库读出数据分页显示
    往数据库批量插入试验数据
    JDK9对集合添加的优化
    全栈工程师
    List的三个子类的特点
    List集合
  • 原文地址:https://www.cnblogs.com/yaowen/p/6958136.html
Copyright © 2020-2023  润新知