// 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>