No ticket: Reduce size in anticipation of Sizzle-free builds
[jquery.git] / src / offset.js
blobb616a49a005dd25ef708a2676c01cad9db2adb2b
1 jQuery.fn.offset = function( options ) {
2         if ( arguments.length ) {
3                 return options === undefined ?
4                         this :
5                         this.each(function( i ) {
6                                 jQuery.offset.setOffset( this, options, i );
7                         });
8         }
10         var docElem, win,
11                 elem = this[ 0 ],
12                 box = { top: 0, left: 0 },
13                 doc = elem && elem.ownerDocument;
15         if ( !doc ) {
16                 return;
17         }
19         docElem = doc.documentElement;
21         // Make sure it's not a disconnected DOM node
22         if ( !jQuery.contains( docElem, elem ) ) {
23                 return box;
24         }
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();
30         }
31         win = getWindow( doc );
32         return {
33                 top: box.top + win.pageYOffset - docElem.clientTop,
34                 left: box.left + win.pageXOffset - docElem.clientLeft
35         };
38 jQuery.offset = {
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 ),
44                         props = {};
46                 // Set position first, in-case top/left are set even on static elem
47                 if ( position === "static" ) {
48                         elem.style.position = "relative";
49                 }
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;
62                 } else {
63                         curTop = parseFloat( curCSSTop ) || 0;
64                         curLeft = parseFloat( curCSSLeft ) || 0;
65                 }
67                 if ( jQuery.isFunction( options ) ) {
68                         options = options.call( elem, i, curOffset );
69                 }
71                 if ( options.top != null ) {
72                         props.top = ( options.top - curOffset.top ) + curTop;
73                 }
74                 if ( options.left != null ) {
75                         props.left = ( options.left - curOffset.left ) + curLeft;
76                 }
78                 if ( "using" in options ) {
79                         options.using.call( elem, props );
81                 } else {
82                         curElem.css( props );
83                 }
84         }
88 jQuery.fn.extend({
90         position: function() {
91                 if ( !this[ 0 ] ) {
92                         return;
93                 }
95                 var offsetParent, offset,
96                         elem = this[ 0 ],
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();
104                 } else {
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();
112                         }
114                         // Add offsetParent borders
115                         parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
116                         parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
117                 }
119                 // Subtract parent offsets and element margins
120                 return {
121                         top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
122                         left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true )
123                 };
124         },
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;
132                         }
134                         return offsetParent || docElem;
135                 });
136         }
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 ];
150                         }
152                         if ( win ) {
153                                 win.scrollTo(
154                                         !top ? val : window.pageXOffset,
155                                         top ? val : window.pageYOffset
156                                 );
158                         } else {
159                                 elem[ method ] = val;
160                         }
161                 }, method, val, arguments.length, null );
162         };
165 function getWindow( elem ) {
166         return jQuery.isWindow( elem ) ? elem : elem.nodeType === 9 && elem.defaultView;