Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 31 additions & 26 deletions src/offset.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,12 @@ define( [
"./css/curCSS",
"./css/addGetHookIf",
"./css/support",
"./core/nodeName",

"./core/init",
"./css",
"./selector" // contains
], function( jQuery, access, document, documentElement, rnumnonpx,
curCSS, addGetHookIf, support, nodeName ) {
curCSS, addGetHookIf, support ) {

"use strict";

Expand Down Expand Up @@ -70,6 +69,8 @@ jQuery.offset = {
};

jQuery.fn.extend( {

// offset() relates an element's border box to the document origin
offset: function( options ) {

// Preserve chaining for setter
Expand All @@ -81,7 +82,7 @@ jQuery.fn.extend( {
} );
}

var doc, docElem, rect, win,
var rect, win,
elem = this[ 0 ];

if ( !elem ) {
Expand All @@ -96,50 +97,54 @@ jQuery.fn.extend( {
return { top: 0, left: 0 };
}

// Get document-relative position by adding viewport scroll to viewport-relative gBCR
rect = elem.getBoundingClientRect();

doc = elem.ownerDocument;
docElem = doc.documentElement;
win = doc.defaultView;

win = elem.ownerDocument.defaultView;
return {
top: rect.top + win.pageYOffset - docElem.clientTop,
left: rect.left + win.pageXOffset - docElem.clientLeft
top: rect.top + win.pageYOffset,
left: rect.left + win.pageXOffset
};
},

// position() relates an element's margin box to its offset parent's padding box
// This corresponds to the behavior of CSS absolute positioning
position: function() {
if ( !this[ 0 ] ) {
return;
}

var offsetParent, offset,
var offsetParent, offset, doc,
elem = this[ 0 ],
parentOffset = { top: 0, left: 0 };

// Fixed elements are offset from window (parentOffset = {top:0, left: 0},
// because it is its only offset parent
// position:fixed elements are offset from the viewport, which itself always has zero offset
if ( jQuery.css( elem, "position" ) === "fixed" ) {

// Assume getBoundingClientRect is there when computed position is fixed
// Assume position:fixed implies availability of getBoundingClientRect
offset = elem.getBoundingClientRect();

} else {
offset = this.offset();

// Get *real* offsetParent
offsetParent = this.offsetParent();
// Account for the *real* offset parent, which can be the document or its root element
// when a statically positioned element is identified
doc = elem.ownerDocument;
offsetParent = elem.offsetParent || doc.documentElement;
while ( offsetParent &&
( offsetParent === doc.body || offsetParent === doc.documentElement ) &&
jQuery.css( offsetParent, "position" ) === "static" ) {

// Get correct offsets
offset = this.offset();
if ( !nodeName( offsetParent[ 0 ], "html" ) ) {
parentOffset = offsetParent.offset();
offsetParent = offsetParent.parentNode;
}
if ( offsetParent && offsetParent !== elem && offsetParent.nodeType === 1 ) {

// Incorporate borders into its offset, since they are outside its content origin
parentOffset = jQuery( offsetParent ).offset();
parentOffset = {
top: parentOffset.top + jQuery.css( offsetParent, "borderTopWidth", true ),
left: parentOffset.left + jQuery.css( offsetParent, "borderLeftWidth", true )
};
}

// Add offsetParent borders
parentOffset = {
top: parentOffset.top + jQuery.css( offsetParent[ 0 ], "borderTopWidth", true ),
left: parentOffset.left + jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true )
};
}

// Subtract parent offsets and element margins
Expand Down
99 changes: 99 additions & 0 deletions test/data/offset/boxes.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html id="documentElement" class="box">
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<meta name="description" content="horizontal values 2^N; vertical doubled">
<title>Nonempty margin/border/padding/position</title>
<style type="text/css" media="screen">
/* work with convenient classes, units, and dimensions */
.static { position: static; }
.relative { position: relative; }
.absolute { position: absolute; }
.fixed { position: fixed; }
.box {
font-size: 4px;
border-style: solid;
min-width: 300px;
}

/* start the exponential scales, reserving the first bit for scroll position */
.box {
border-width: 1em 0.5em;
top: 2em; left: 1em;
margin: 4em 2em;
padding: 8em 4em;
}
#documentElement {
margin: 16em 8em;
border-width: 32em 16em;
padding: 64em 32em;
}
#body {
margin: 128em 64em;
border-width: 256em 128em;
padding: 512em 256em;
}
#documentElement {
top: 1024em; left: 512em;
}
#body {
top: 2048em; left: 1024em;
}

/* style for humans */
:not(.box) {
font-size: 20px;
}
html {
border-color: hsl(20, 100%, 70%);
background-color: hsl(110, 100%, 70%);
}
body {
border-color: hsl(200, 100%, 70%);
background-color: hsl(290, 100%, 70%);
}
html::after,
body::after {
font: italic 16px sans-serif;
content: attr(id);
}
div.box {
background-color: hsla(0, 0%, 70%, 0.5);
opacity: 0.7;
}
div.box div.box {
background-color: hsla(60, 100%, 70%, 0.5);
}
</style>
<script src="../../jquery.js"></script>
<script src="../iframeTest.js"></script>
<script type="text/javascript" charset="utf-8">
jQuery( function() {
window.scrollTo( 1, 2 );
startIframeTest();
} );
</script>
</head>
<body id="body" class="box">
<div id="relative" class="relative box">
<div id="relative-relative" class="relative box"><code
>relative &gt; relative</code></div>
<div id="relative-absolute" class="absolute box"><code
>relative &gt; absolute</code></div>
</div>
<div id="absolute" class="absolute box">
<div id="absolute-relative" class="relative box"><code
>absolute &gt; relative</code></div>
<div id="absolute-absolute" class="absolute box"><code
>absolute &gt; absolute</code></div>
</div>
<div id="fixed" class="fixed box">
<div id="fixed-relative" class="relative box"><code
>fixed &gt; relative</code></div>
<div id="fixed-absolute" class="absolute box"><code
>fixed &gt; absolute</code></div>
</div>
<p id="positionTest" class="absolute">position:absolute with no top/left values</p>
</body>
</html>
Loading