Offset: Fix .offset() to correctly work with ShadowDOM

Fixes gh-1784
Close gh-2043
This commit is contained in:
Arthur Stolyar 2015-05-05 08:16:29 -07:00 committed by Timmy Willison
parent 17ce9edf1e
commit d4dd548aca
2 changed files with 37 additions and 19 deletions

View File

@ -39,7 +39,7 @@ jQuery.offset = {
elem.style.position = "relative"; elem.style.position = "relative";
} }
curOffset = curElem.offset(); curOffset = curElem.offset() || { top: 0, left: 0 };
curCSSTop = jQuery.css( elem, "top" ); curCSSTop = jQuery.css( elem, "top" );
curCSSLeft = jQuery.css( elem, "left" ); curCSSLeft = jQuery.css( elem, "left" );
calculatePosition = ( position === "absolute" || position === "fixed" ) && calculatePosition = ( position === "absolute" || position === "fixed" ) &&
@ -87,8 +87,7 @@ jQuery.fn.extend({
}); });
} }
var docElem, win, var docElem, win, rect,
box = { top: 0, left: 0 },
elem = this[ 0 ], elem = this[ 0 ],
doc = elem && elem.ownerDocument; doc = elem && elem.ownerDocument;
@ -96,19 +95,20 @@ jQuery.fn.extend({
return; return;
} }
rect = elem.getBoundingClientRect();
// Make sure element is not hidden (display: none) or disconnected
if ( rect.width || rect.height || elem.getClientRects().length ) {
win = getWindow( doc );
docElem = doc.documentElement; docElem = doc.documentElement;
// Make sure it's not a disconnected DOM node
if ( !jQuery.contains( docElem, elem ) ) {
return box;
}
box = elem.getBoundingClientRect();
win = getWindow( doc );
return { return {
top: box.top + ( win.pageYOffset || docElem.scrollTop ) - ( docElem.clientTop || 0 ), top: rect.top + ( win.pageYOffset || docElem.scrollTop ) -
left: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 ) ( docElem.clientTop || 0 ),
left: rect.left + ( win.pageXOffset || docElem.scrollLeft ) -
( docElem.clientLeft || 0 )
}; };
}
}, },
position: function() { position: function() {

View File

@ -57,13 +57,31 @@ test("object without getBoundingClientRect", function() {
equal( result.left, 0, "Check left" ); equal( result.left, 0, "Check left" );
}); });
test("disconnected node", function() { test("disconnected element", function() {
expect(2); expect(1);
var result = jQuery( document.createElement("div") ).offset(); var result;
equal( result.top, 0, "Check top" ); try {
equal( result.left, 0, "Check left" ); result = jQuery( document.createElement("div") ).offset();
} catch ( e ) {}
ok( !result, "no position for disconnected element" );
});
test("hidden (display: none) element", function() {
expect(1);
var result,
node = jQuery("<div style='display: none' />").appendTo("#qunit-fixture");
try {
result = node.offset();
} catch ( e ) {}
node.remove();
ok( !result, "no position for hidden (display: none) element" );
}); });
testIframe("offset/absolute", "absolute", function($, iframe) { testIframe("offset/absolute", "absolute", function($, iframe) {