1 jQuery.fn.offset = function( options ) {
2 if ( arguments.length ) {
3 return options === undefined ?
5 this.each(function( i ) {
6 jQuery.offset.setOffset( this, options, i );
12 box = { top: 0, left: 0 },
13 doc = elem && elem.ownerDocument;
19 docElem = doc.documentElement;
21 // Make sure it's not a disconnected DOM node
22 if ( !jQuery.contains( docElem, elem ) ) {
26 // If we don't have gBCR, just use 0,0 rather than error
27 // BlackBerry 5, iOS 3 (original iPhone)
28 if ( typeof elem.getBoundingClientRect !== core_strundefined ) {
29 box = elem.getBoundingClientRect();
31 win = getWindow( doc );
33 top: box.top + win.pageYOffset - docElem.clientTop,
34 left: box.left + win.pageXOffset - docElem.clientLeft
40 setOffset: function( elem, options, i ) {
41 var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
42 position = jQuery.css( elem, "position" ),
43 curElem = jQuery( elem ),
46 // Set position first, in-case top/left are set even on static elem
47 if ( position === "static" ) {
48 elem.style.position = "relative";
51 curOffset = curElem.offset();
52 curCSSTop = jQuery.css( elem, "top" );
53 curCSSLeft = jQuery.css( elem, "left" );
54 calculatePosition = ( position === "absolute" || position === "fixed" ) && ( curCSSTop + curCSSLeft ).indexOf("auto") > -1;
56 // Need to be able to calculate position if either top or left is auto and position is either absolute or fixed
57 if ( calculatePosition ) {
58 curPosition = curElem.position();
59 curTop = curPosition.top;
60 curLeft = curPosition.left;
63 curTop = parseFloat( curCSSTop ) || 0;
64 curLeft = parseFloat( curCSSLeft ) || 0;
67 if ( jQuery.isFunction( options ) ) {
68 options = options.call( elem, i, curOffset );
71 if ( options.top != null ) {
72 props.top = ( options.top - curOffset.top ) + curTop;
74 if ( options.left != null ) {
75 props.left = ( options.left - curOffset.left ) + curLeft;
78 if ( "using" in options ) {
79 options.using.call( elem, props );
90 position: function() {
95 var offsetParent, offset,
97 parentOffset = { top: 0, left: 0 };
99 // Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is it's only offset parent
100 if ( jQuery.css( elem, "position" ) === "fixed" ) {
101 // We assume that getBoundingClientRect is available when computed position is fixed
102 offset = elem.getBoundingClientRect();
105 // Get *real* offsetParent
106 offsetParent = this.offsetParent();
108 // Get correct offsets
109 offset = this.offset();
110 if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
111 parentOffset = offsetParent.offset();
114 // Add offsetParent borders
115 parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
116 parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
119 // Subtract parent offsets and element margins
121 top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
122 left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true )
126 offsetParent: function() {
127 return this.map(function() {
128 var offsetParent = this.offsetParent || docElem;
130 while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position") === "static" ) ) {
131 offsetParent = offsetParent.offsetParent;
134 return offsetParent || docElem;
140 // Create scrollLeft and scrollTop methods
141 jQuery.each( {scrollLeft: "pageXOffset", scrollTop: "pageYOffset"}, function( method, prop ) {
142 var top = "pageYOffset" === prop;
144 jQuery.fn[ method ] = function( val ) {
145 return jQuery.access( this, function( elem, method, val ) {
146 var win = getWindow( elem );
148 if ( val === undefined ) {
149 return win ? win[ prop ] : elem[ method ];
154 !top ? val : window.pageXOffset,
155 top ? val : window.pageYOffset
159 elem[ method ] = val;
161 }, method, val, arguments.length, null );
165 function getWindow( elem ) {
166 return jQuery.isWindow( elem ) ? elem : elem.nodeType === 9 && elem.defaultView;