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