jQuery.fn.extend({
position: function() {
- if ( !this[0] ) {
+ if ( !this[ 0 ] ) {
return;
}
- var elem = this[0],
+ var offsetParent, offset,
+ parentOffset = { top: 0, left: 0 },
+ elem = this[ 0 ];
- // Get *real* offsetParent
- offsetParent = this.offsetParent(),
+ // fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is it's only offset parent
+ 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
- offset = this.offset(),
- parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();
+ // Add offsetParent borders
+ parentOffset.top += parseFloat( jQuery.css( offsetParent[ 0 ], "borderTopWidth" ) ) || 0;
+ 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
// 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 {
- top: offset.top - parentOffset.top,
- left: offset.left - parentOffset.left
+ top: offset.top - parentOffset.top - ( parseFloat( jQuery.css( elem, "marginTop" ) ) || 0 ),
+ left: offset.left - parentOffset.left - ( parseFloat( jQuery.css( elem, "marginLeft" ) ) || 0 )
};
},
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
equal( result.left, 0, "Check left" );
});
-var supportsScroll = false;
-
testIframe("offset/absolute", "absolute", function($, iframe) {
expect(4);
var doc = iframe.document,
- tests, forceScroll;
-
- // 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);
+ tests;
// get offset
tests = [
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" );
});
-
- forceScroll.remove();
});
testIframe("offset/absolute", "absolute", function( $ ) {
});
testIframe("offset/fixed", "fixed", function( $ ) {
- expect(30);
+ expect(34);
var tests = [
- { "id": "#fixed-1", "top": 1001, "left": 1001 },
- { "id": "#fixed-2", "top": 1021, "left": 1021 }
+ { "id": "#fixed-1", "offsetTop": 1001, "offsetLeft": 1001, "positionTop": 0, "positionLeft": 0 },
+ { "id": "#fixed-2", "offsetTop": 1021, "offsetLeft": 1021, "positionTop": 20, "positionLeft": 20 }
];
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." );
- } else if ( jQuery.offset.supportsFixedPosition ) {
- equal( $( this["id"] ).offset().top, this["top"], "jQuery('" + this["id"] + "').offset().top" );
- equal( $( this["id"] ).offset().left, this["left"], "jQuery('" + this["id"] + "').offset().left" );
+ } else if ( window.supportsFixedPosition ) {
+ equal( $( this["id"] ).offset().top, this["offsetTop"], "jQuery('" + this["id"] + "').offset().top" );
+ 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 {
// need to have same number of assertions
ok( true, "Fixed position is not supported" );
];
jQuery.each( tests, function() {
- if ( jQuery.offset.supportsFixedPosition ) {
+ if ( window.supportsFixedPosition ) {
$( 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().left, this["left"], "jQuery('" + this["id"] + "').offset({ left: " + this["left"] + " })" );
// Bug 8316
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().left, 1007, "Check offset left for fixed element with no left set" );
} else {
win.name = "test";
- if ( !supportsScroll ) {
+ if ( !window.supportsScroll ) {
ok( true, "Browser doesn't support scroll position." );
ok( true, "Browser doesn't support scroll position." );