11 "./selector" // contains
12 ], function( jQuery, access, rnumnonpx, curCSS, addGetHookIf, support ) {
15 curCSS = curCSS.curCSS;
17 var docElem = window.document.documentElement;
20 * Gets a window from an element
22 function getWindow( elem ) {
23 return jQuery.isWindow( elem ) ?
26 elem.defaultView || elem.parentWindow :
31 setOffset: function( elem, options, i ) {
32 var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
33 position = jQuery.css( elem, "position" ),
34 curElem = jQuery( elem ),
37 // set position first, in-case top/left are set even on static elem
38 if ( position === "static" ) {
39 elem.style.position = "relative";
42 curOffset = curElem.offset();
43 curCSSTop = jQuery.css( elem, "top" );
44 curCSSLeft = jQuery.css( elem, "left" );
45 calculatePosition = ( position === "absolute" || position === "fixed" ) &&
46 jQuery.inArray("auto", [ curCSSTop, curCSSLeft ] ) > -1;
48 // need to be able to calculate position if either top or left
49 // is auto and position is either absolute or fixed
50 if ( calculatePosition ) {
51 curPosition = curElem.position();
52 curTop = curPosition.top;
53 curLeft = curPosition.left;
55 curTop = parseFloat( curCSSTop ) || 0;
56 curLeft = parseFloat( curCSSLeft ) || 0;
59 if ( jQuery.isFunction( options ) ) {
61 // Use jQuery.extend here to allow modification of coordinates argument (gh-1848)
62 options = options.call( elem, i, jQuery.extend( {}, curOffset ) );
65 if ( options.top != null ) {
66 props.top = ( options.top - curOffset.top ) + curTop;
68 if ( options.left != null ) {
69 props.left = ( options.left - curOffset.left ) + curLeft;
72 if ( "using" in options ) {
73 options.using.call( elem, props );
81 offset: function( options ) {
82 // Preserve chaining for setter
83 if ( arguments.length ) {
84 return options === undefined ?
86 this.each(function( i ) {
87 jQuery.offset.setOffset( this, options, i );
91 var docElem, win, rect, doc,
98 rect = elem.getBoundingClientRect();
100 // Make sure element is not hidden (display: none) or disconnected
101 if ( rect.width || rect.height || elem.getClientRects().length ) {
102 doc = elem.ownerDocument;
103 win = getWindow( doc );
104 docElem = doc.documentElement;
107 top: rect.top + ( win.pageYOffset || docElem.scrollTop ) -
108 ( docElem.clientTop || 0 ),
109 left: rect.left + ( win.pageXOffset || docElem.scrollLeft ) -
110 ( docElem.clientLeft || 0 )
115 position: function() {
120 var offsetParent, offset,
121 parentOffset = { top: 0, left: 0 },
124 // Fixed elements are offset from window (parentOffset = {top:0, left: 0},
125 // because it is its only offset parent
126 if ( jQuery.css( elem, "position" ) === "fixed" ) {
127 // we assume that getBoundingClientRect is available when computed position is fixed
128 offset = elem.getBoundingClientRect();
130 // Get *real* offsetParent
131 offsetParent = this.offsetParent();
133 // Get correct offsets
134 offset = this.offset();
135 if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
136 parentOffset = offsetParent.offset();
139 // Add offsetParent borders
140 parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
141 parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
144 // Subtract parent offsets and element margins
145 // note: when an element has margin: auto the offsetLeft and marginLeft
146 // are the same in Safari causing offset.left to incorrectly be 0
148 top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
149 left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true)
153 // This method will return documentElement in the following cases:
154 // 1) For the element inside the iframe without offsetParent, this method will return
155 // documentElement of the parent window
156 // 2) For the hidden or detached element
157 // 3) For body or html element, i.e. in case of the html node - it will return itself
159 // but those exceptions were never presented as a real life use-cases
160 // and might be considered as more preferable results.
162 // This logic, however, is not guaranteed and can change at any point in the future
163 offsetParent: function() {
164 return this.map(function() {
165 var offsetParent = this.offsetParent;
167 while ( offsetParent && jQuery.css( offsetParent, "position" ) === "static" ) {
168 offsetParent = offsetParent.offsetParent;
171 return offsetParent || docElem;
176 // Create scrollLeft and scrollTop methods
177 jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
178 var top = /Y/.test( prop );
180 jQuery.fn[ method ] = function( val ) {
181 return access( this, function( elem, method, val ) {
182 var win = getWindow( elem );
184 if ( val === undefined ) {
185 return win ? (prop in win) ? win[ prop ] :
186 win.document.documentElement[ method ] :
192 !top ? val : jQuery( win ).scrollLeft(),
193 top ? val : jQuery( win ).scrollTop()
197 elem[ method ] = val;
199 }, method, val, arguments.length, null );
203 // Add the top/left cssHooks using jQuery.fn.position
204 // Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
205 // getComputedStyle returns percent when specified for top/left/bottom/right
206 // rather than make the css module depend on the offset module, we just check for it here
207 jQuery.each( [ "top", "left" ], function( i, prop ) {
208 jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
209 function( elem, computed ) {
211 computed = curCSS( elem, prop );
212 // if curCSS returns percentage, fallback to offset
213 return rnumnonpx.test( computed ) ?
214 jQuery( elem ).position()[ prop ] + "px" :