Commit 425272ae authored by Merrifield, Jay's avatar Merrifield, Jay Committed by Mike Sherov

Fixes #12749, correctly detect position() for position:fixed elements, closes gh-991

parent 995f816c
...@@ -107,33 +107,39 @@ jQuery.offset = { ...@@ -107,33 +107,39 @@ jQuery.offset = {
jQuery.fn.extend({ jQuery.fn.extend({
position: function() { position: function() {
if ( !this[0] ) { if ( !this[ 0 ] ) {
return; return;
} }
var elem = this[0], var offsetParent, offset,
parentOffset = { top: 0, left: 0 },
elem = this[ 0 ];
// Get *real* offsetParent // fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is it's only offset parent
offsetParent = this.offsetParent(), if ( jQuery.css( elem, "position" ) === "fixed" ) {
// we assume that getBoundingClientRect is available when computed position is fixed
offset = elem.getBoundingClientRect();
} else {
// Get *real* offsetParent
offsetParent = this.offsetParent();
// Get correct offsets
offset = this.offset();
if ( !rroot.test( offsetParent[ 0 ].nodeName ) ) {
parentOffset = offsetParent.offset();
}
// Get correct offsets // Add offsetParent borders
offset = this.offset(), parentOffset.top += parseFloat( jQuery.css( offsetParent[ 0 ], "borderTopWidth" ) ) || 0;
parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset(); parentOffset.left += parseFloat( jQuery.css( offsetParent[ 0 ], "borderLeftWidth" ) ) || 0;
}
// Subtract element margins // Subtract parent offsets and element margins
// note: when an element has margin: auto the offsetLeft and marginLeft // note: when an element has margin: auto the offsetLeft and marginLeft
// are the same in Safari causing offset.left to incorrectly be 0 // are the same in Safari causing offset.left to incorrectly be 0
offset.top -= parseFloat( jQuery.css(elem, "marginTop") ) || 0;
offset.left -= parseFloat( jQuery.css(elem, "marginLeft") ) || 0;
// Add offsetParent borders
parentOffset.top += parseFloat( jQuery.css(offsetParent[0], "borderTopWidth") ) || 0;
parentOffset.left += parseFloat( jQuery.css(offsetParent[0], "borderLeftWidth") ) || 0;
// Subtract the two offsets
return { return {
top: offset.top - parentOffset.top, top: offset.top - parentOffset.top - ( parseFloat( jQuery.css( elem, "marginTop" ) ) || 0 ),
left: offset.left - parentOffset.left left: offset.left - parentOffset.left - ( parseFloat( jQuery.css( elem, "marginLeft" ) ) || 0 )
}; };
}, },
......
if ( jQuery.fn.offset ) { if ( jQuery.fn.offset ) {
module("offset", { teardown: moduleTeardown }); module("offset", { setup: function(){
// force a scroll value on the main window
// this insures that the results will be wrong
// if the offset method is using the scroll offset
// of the parent window
var forceScroll = jQuery("<div>").css({ "width": 2000, "height": 2000 });
// this needs to be body, because #qunit-fixture is hidden and elements inside it don't have a scrollTop
forceScroll.appendTo("body");
var checkDiv = jQuery("<div>").appendTo("#qunit-fixture")[0];
window.scrollTo( 200, 200 );
window.supportsScroll = ( document.documentElement.scrollTop || document.body.scrollTop );
window.scrollTo( 1, 1 );
checkDiv.style.position = "fixed";
checkDiv.style.top = "20px";
// safari subtracts parent border width here which is 5px
window.supportsFixedPosition = ( checkDiv.offsetTop === 20 || checkDiv.offsetTop === 15 );
checkDiv.style.position = checkDiv.style.top = "";
jQuery( checkDiv ).remove();
forceScroll.remove();
}, teardown: moduleTeardown });
/* /*
Closure-compiler will roll static methods off of the jQuery object and so they will Closure-compiler will roll static methods off of the jQuery object and so they will
...@@ -33,28 +54,11 @@ test("disconnected node", function() { ...@@ -33,28 +54,11 @@ test("disconnected node", function() {
equal( result.left, 0, "Check left" ); equal( result.left, 0, "Check left" );
}); });
var supportsScroll = false;
testIframe("offset/absolute", "absolute", function($, iframe) { testIframe("offset/absolute", "absolute", function($, iframe) {
expect(4); expect(4);
var doc = iframe.document, var doc = iframe.document,
tests, forceScroll; tests;
// force a scroll value on the main window
// this insures that the results will be wrong
// if the offset method is using the scroll offset
// of the parent window
forceScroll = jQuery("<div>").css({ "width": 2000, "height": 2000 });
forceScroll.appendTo("body");
window.scrollTo(200, 200);
if ( document.documentElement.scrollTop || document.body.scrollTop ) {
supportsScroll = true;
}
window.scrollTo(1, 1);
// get offset // get offset
tests = [ tests = [
...@@ -74,8 +78,6 @@ testIframe("offset/absolute", "absolute", function($, iframe) { ...@@ -74,8 +78,6 @@ testIframe("offset/absolute", "absolute", function($, iframe) {
equal( jQuery( this["id"], doc ).position().top, this["top"], "jQuery('" + this["id"] + "').position().top" ); equal( jQuery( this["id"], doc ).position().top, this["top"], "jQuery('" + this["id"] + "').position().top" );
equal( jQuery( this["id"], doc ).position().left, this["left"], "jQuery('" + this["id"] + "').position().left" ); equal( jQuery( this["id"], doc ).position().left, this["left"], "jQuery('" + this["id"] + "').position().left" );
}); });
forceScroll.remove();
}); });
testIframe("offset/absolute", "absolute", function( $ ) { testIframe("offset/absolute", "absolute", function( $ ) {
...@@ -293,21 +295,25 @@ testIframe("offset/static", "static", function( $ ) { ...@@ -293,21 +295,25 @@ testIframe("offset/static", "static", function( $ ) {
}); });
testIframe("offset/fixed", "fixed", function( $ ) { testIframe("offset/fixed", "fixed", function( $ ) {
expect(30); expect(34);
var tests = [ var tests = [
{ "id": "#fixed-1", "top": 1001, "left": 1001 }, { "id": "#fixed-1", "offsetTop": 1001, "offsetLeft": 1001, "positionTop": 0, "positionLeft": 0 },
{ "id": "#fixed-2", "top": 1021, "left": 1021 } { "id": "#fixed-2", "offsetTop": 1021, "offsetLeft": 1021, "positionTop": 20, "positionLeft": 20 }
]; ];
jQuery.each( tests, function() { jQuery.each( tests, function() {
if ( !supportsScroll ) { if ( !window.supportsScroll ) {
ok( true, "Browser doesn't support scroll position." );
ok( true, "Browser doesn't support scroll position." );
ok( true, "Browser doesn't support scroll position." ); ok( true, "Browser doesn't support scroll position." );
ok( true, "Browser doesn't support scroll position." ); ok( true, "Browser doesn't support scroll position." );
} else if ( jQuery.offset.supportsFixedPosition ) { } else if ( window.supportsFixedPosition ) {
equal( $( this["id"] ).offset().top, this["top"], "jQuery('" + this["id"] + "').offset().top" ); equal( $( this["id"] ).offset().top, this["offsetTop"], "jQuery('" + this["id"] + "').offset().top" );
equal( $( this["id"] ).offset().left, this["left"], "jQuery('" + this["id"] + "').offset().left" ); equal( $( this["id"] ).position().top, this["positionTop"], "jQuery('" + this["id"] + "').position().top" );
equal( $( this["id"] ).offset().left, this["offsetLeft"], "jQuery('" + this["id"] + "').offset().left" );
equal( $( this["id"] ).position().left, this["positionLeft"], "jQuery('" + this["id"] + "').position().left" );
} else { } else {
// need to have same number of assertions // need to have same number of assertions
ok( true, "Fixed position is not supported" ); ok( true, "Fixed position is not supported" );
...@@ -325,7 +331,7 @@ testIframe("offset/fixed", "fixed", function( $ ) { ...@@ -325,7 +331,7 @@ testIframe("offset/fixed", "fixed", function( $ ) {
]; ];
jQuery.each( tests, function() { jQuery.each( tests, function() {
if ( jQuery.offset.supportsFixedPosition ) { if ( window.supportsFixedPosition ) {
$( this["id"] ).offset({ "top": this["top"], "left": this["left"] }); $( this["id"] ).offset({ "top": this["top"], "left": this["left"] });
equal( $( this["id"] ).offset().top, this["top"], "jQuery('" + this["id"] + "').offset({ top: " + this["top"] + " })" ); equal( $( this["id"] ).offset().top, this["top"], "jQuery('" + this["id"] + "').offset({ top: " + this["top"] + " })" );
equal( $( this["id"] ).offset().left, this["left"], "jQuery('" + this["id"] + "').offset({ left: " + this["left"] + " })" ); equal( $( this["id"] ).offset().left, this["left"], "jQuery('" + this["id"] + "').offset({ left: " + this["left"] + " })" );
...@@ -349,7 +355,7 @@ testIframe("offset/fixed", "fixed", function( $ ) { ...@@ -349,7 +355,7 @@ testIframe("offset/fixed", "fixed", function( $ ) {
// Bug 8316 // Bug 8316
var $noTopLeft = $("#fixed-no-top-left"); var $noTopLeft = $("#fixed-no-top-left");
if ( jQuery.offset.supportsFixedPosition ) { if ( window.supportsFixedPosition ) {
equal( $noTopLeft.offset().top, 1007, "Check offset top for fixed element with no top set" ); equal( $noTopLeft.offset().top, 1007, "Check offset top for fixed element with no top set" );
equal( $noTopLeft.offset().left, 1007, "Check offset left for fixed element with no left set" ); equal( $noTopLeft.offset().left, 1007, "Check offset left for fixed element with no left set" );
} else { } else {
...@@ -397,7 +403,7 @@ testIframe("offset/scroll", "scroll", function( $, win ) { ...@@ -397,7 +403,7 @@ testIframe("offset/scroll", "scroll", function( $, win ) {
win.name = "test"; win.name = "test";
if ( !supportsScroll ) { if ( !window.supportsScroll ) {
ok( true, "Browser doesn't support scroll position." ); ok( true, "Browser doesn't support scroll position." );
ok( true, "Browser doesn't support scroll position." ); ok( true, "Browser doesn't support scroll position." );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment