0
|
1 define( [
|
|
2 "./core",
|
|
3 "./core/access",
|
|
4 "./var/document",
|
|
5 "./var/documentElement",
|
|
6 "./var/isFunction",
|
|
7 "./css/var/rnumnonpx",
|
|
8 "./css/curCSS",
|
|
9 "./css/addGetHookIf",
|
|
10 "./css/support",
|
|
11 "./var/isWindow",
|
|
12 "./core/init",
|
|
13 "./css",
|
|
14 "./selector" // contains
|
|
15 ], function( jQuery, access, document, documentElement, isFunction, rnumnonpx,
|
|
16 curCSS, addGetHookIf, support, isWindow ) {
|
|
17
|
|
18 "use strict";
|
|
19
|
|
20 jQuery.offset = {
|
|
21 setOffset: function( elem, options, i ) {
|
|
22 var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
|
|
23 position = jQuery.css( elem, "position" ),
|
|
24 curElem = jQuery( elem ),
|
|
25 props = {};
|
|
26
|
|
27 // Set position first, in-case top/left are set even on static elem
|
|
28 if ( position === "static" ) {
|
|
29 elem.style.position = "relative";
|
|
30 }
|
|
31
|
|
32 curOffset = curElem.offset();
|
|
33 curCSSTop = jQuery.css( elem, "top" );
|
|
34 curCSSLeft = jQuery.css( elem, "left" );
|
|
35 calculatePosition = ( position === "absolute" || position === "fixed" ) &&
|
|
36 ( curCSSTop + curCSSLeft ).indexOf( "auto" ) > -1;
|
|
37
|
|
38 // Need to be able to calculate position if either
|
|
39 // top or left is auto and position is either absolute or fixed
|
|
40 if ( calculatePosition ) {
|
|
41 curPosition = curElem.position();
|
|
42 curTop = curPosition.top;
|
|
43 curLeft = curPosition.left;
|
|
44
|
|
45 } else {
|
|
46 curTop = parseFloat( curCSSTop ) || 0;
|
|
47 curLeft = parseFloat( curCSSLeft ) || 0;
|
|
48 }
|
|
49
|
|
50 if ( isFunction( options ) ) {
|
|
51
|
|
52 // Use jQuery.extend here to allow modification of coordinates argument (gh-1848)
|
|
53 options = options.call( elem, i, jQuery.extend( {}, curOffset ) );
|
|
54 }
|
|
55
|
|
56 if ( options.top != null ) {
|
|
57 props.top = ( options.top - curOffset.top ) + curTop;
|
|
58 }
|
|
59 if ( options.left != null ) {
|
|
60 props.left = ( options.left - curOffset.left ) + curLeft;
|
|
61 }
|
|
62
|
|
63 if ( "using" in options ) {
|
|
64 options.using.call( elem, props );
|
|
65
|
|
66 } else {
|
|
67 curElem.css( props );
|
|
68 }
|
|
69 }
|
|
70 };
|
|
71
|
|
72 jQuery.fn.extend( {
|
|
73
|
|
74 // offset() relates an element's border box to the document origin
|
|
75 offset: function( options ) {
|
|
76
|
|
77 // Preserve chaining for setter
|
|
78 if ( arguments.length ) {
|
|
79 return options === undefined ?
|
|
80 this :
|
|
81 this.each( function( i ) {
|
|
82 jQuery.offset.setOffset( this, options, i );
|
|
83 } );
|
|
84 }
|
|
85
|
|
86 var rect, win,
|
|
87 elem = this[ 0 ];
|
|
88
|
|
89 if ( !elem ) {
|
|
90 return;
|
|
91 }
|
|
92
|
|
93 // Return zeros for disconnected and hidden (display: none) elements (gh-2310)
|
|
94 // Support: IE <=11 only
|
|
95 // Running getBoundingClientRect on a
|
|
96 // disconnected node in IE throws an error
|
|
97 if ( !elem.getClientRects().length ) {
|
|
98 return { top: 0, left: 0 };
|
|
99 }
|
|
100
|
|
101 // Get document-relative position by adding viewport scroll to viewport-relative gBCR
|
|
102 rect = elem.getBoundingClientRect();
|
|
103 win = elem.ownerDocument.defaultView;
|
|
104 return {
|
|
105 top: rect.top + win.pageYOffset,
|
|
106 left: rect.left + win.pageXOffset
|
|
107 };
|
|
108 },
|
|
109
|
|
110 // position() relates an element's margin box to its offset parent's padding box
|
|
111 // This corresponds to the behavior of CSS absolute positioning
|
|
112 position: function() {
|
|
113 if ( !this[ 0 ] ) {
|
|
114 return;
|
|
115 }
|
|
116
|
|
117 var offsetParent, offset, doc,
|
|
118 elem = this[ 0 ],
|
|
119 parentOffset = { top: 0, left: 0 };
|
|
120
|
|
121 // position:fixed elements are offset from the viewport, which itself always has zero offset
|
|
122 if ( jQuery.css( elem, "position" ) === "fixed" ) {
|
|
123
|
|
124 // Assume position:fixed implies availability of getBoundingClientRect
|
|
125 offset = elem.getBoundingClientRect();
|
|
126
|
|
127 } else {
|
|
128 offset = this.offset();
|
|
129
|
|
130 // Account for the *real* offset parent, which can be the document or its root element
|
|
131 // when a statically positioned element is identified
|
|
132 doc = elem.ownerDocument;
|
|
133 offsetParent = elem.offsetParent || doc.documentElement;
|
|
134 while ( offsetParent &&
|
|
135 ( offsetParent === doc.body || offsetParent === doc.documentElement ) &&
|
|
136 jQuery.css( offsetParent, "position" ) === "static" ) {
|
|
137
|
|
138 offsetParent = offsetParent.parentNode;
|
|
139 }
|
|
140 if ( offsetParent && offsetParent !== elem && offsetParent.nodeType === 1 ) {
|
|
141
|
|
142 // Incorporate borders into its offset, since they are outside its content origin
|
|
143 parentOffset = jQuery( offsetParent ).offset();
|
|
144 parentOffset.top += jQuery.css( offsetParent, "borderTopWidth", true );
|
|
145 parentOffset.left += jQuery.css( offsetParent, "borderLeftWidth", true );
|
|
146 }
|
|
147 }
|
|
148
|
|
149 // Subtract parent offsets and element margins
|
|
150 return {
|
|
151 top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
|
|
152 left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true )
|
|
153 };
|
|
154 },
|
|
155
|
|
156 // This method will return documentElement in the following cases:
|
|
157 // 1) For the element inside the iframe without offsetParent, this method will return
|
|
158 // documentElement of the parent window
|
|
159 // 2) For the hidden or detached element
|
|
160 // 3) For body or html element, i.e. in case of the html node - it will return itself
|
|
161 //
|
|
162 // but those exceptions were never presented as a real life use-cases
|
|
163 // and might be considered as more preferable results.
|
|
164 //
|
|
165 // This logic, however, is not guaranteed and can change at any point in the future
|
|
166 offsetParent: function() {
|
|
167 return this.map( function() {
|
|
168 var offsetParent = this.offsetParent;
|
|
169
|
|
170 while ( offsetParent && jQuery.css( offsetParent, "position" ) === "static" ) {
|
|
171 offsetParent = offsetParent.offsetParent;
|
|
172 }
|
|
173
|
|
174 return offsetParent || documentElement;
|
|
175 } );
|
|
176 }
|
|
177 } );
|
|
178
|
|
179 // Create scrollLeft and scrollTop methods
|
|
180 jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
|
|
181 var top = "pageYOffset" === prop;
|
|
182
|
|
183 jQuery.fn[ method ] = function( val ) {
|
|
184 return access( this, function( elem, method, val ) {
|
|
185
|
|
186 // Coalesce documents and windows
|
|
187 var win;
|
|
188 if ( isWindow( elem ) ) {
|
|
189 win = elem;
|
|
190 } else if ( elem.nodeType === 9 ) {
|
|
191 win = elem.defaultView;
|
|
192 }
|
|
193
|
|
194 if ( val === undefined ) {
|
|
195 return win ? win[ prop ] : elem[ method ];
|
|
196 }
|
|
197
|
|
198 if ( win ) {
|
|
199 win.scrollTo(
|
|
200 !top ? val : win.pageXOffset,
|
|
201 top ? val : win.pageYOffset
|
|
202 );
|
|
203
|
|
204 } else {
|
|
205 elem[ method ] = val;
|
|
206 }
|
|
207 }, method, val, arguments.length );
|
|
208 };
|
|
209 } );
|
|
210
|
|
211 // Support: Safari <=7 - 9.1, Chrome <=37 - 49
|
|
212 // Add the top/left cssHooks using jQuery.fn.position
|
|
213 // Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
|
|
214 // Blink bug: https://bugs.chromium.org/p/chromium/issues/detail?id=589347
|
|
215 // getComputedStyle returns percent when specified for top/left/bottom/right;
|
|
216 // rather than make the css module depend on the offset module, just check for it here
|
|
217 jQuery.each( [ "top", "left" ], function( i, prop ) {
|
|
218 jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
|
|
219 function( elem, computed ) {
|
|
220 if ( computed ) {
|
|
221 computed = curCSS( elem, prop );
|
|
222
|
|
223 // If curCSS returns percentage, fallback to offset
|
|
224 return rnumnonpx.test( computed ) ?
|
|
225 jQuery( elem ).position()[ prop ] + "px" :
|
|
226 computed;
|
|
227 }
|
|
228 }
|
|
229 );
|
|
230 } );
|
|
231
|
|
232 return jQuery;
|
|
233 } );
|