Setting the jsonp option to false now inhibits any url manipulation regarding the...
[jquery.git] / src / offset.js
index 365b35a..2040c9d 100644 (file)
@@ -1,8 +1,13 @@
+(function( jQuery ) {
+
+var rtable = /^t(?:able|d|h)$/i,
+       rroot = /^(?:body|html)$/i;
+
 if ( "getBoundingClientRect" in document.documentElement ) {
        jQuery.fn.offset = function( options ) {
-               var elem = this[0];
+               var elem = this[0], box;
 
-               if ( options ) { 
+               if ( options ) {
                        return this.each(function( i ) {
                                jQuery.offset.setOffset( this, options, i );
                        });
@@ -16,10 +21,19 @@ if ( "getBoundingClientRect" in document.documentElement ) {
                        return jQuery.offset.bodyOffset( elem );
                }
 
-               var box = elem.getBoundingClientRect(),
-                       doc = elem.ownerDocument,
-                       body = doc.body,
-                       docElem = doc.documentElement,
+               try {
+                       box = elem.getBoundingClientRect();
+               } catch(e) {}
+
+               var doc = elem.ownerDocument,
+                       docElem = doc.documentElement;
+
+               // Make sure we're not dealing with a disconnected DOM node
+               if ( !box || !jQuery.contains( docElem, elem ) ) {
+                       return box || { top: 0, left: 0 };
+               }
+
+               var body = doc.body,
                        win = getWindow(doc),
                        clientTop  = docElem.clientTop  || body.clientTop  || 0,
                        clientLeft = docElem.clientLeft || body.clientLeft || 0,
@@ -35,7 +49,7 @@ if ( "getBoundingClientRect" in document.documentElement ) {
        jQuery.fn.offset = function( options ) {
                var elem = this[0];
 
-               if ( options ) { 
+               if ( options ) {
                        return this.each(function( i ) {
                                jQuery.offset.setOffset( this, options, i );
                        });
@@ -51,11 +65,16 @@ if ( "getBoundingClientRect" in document.documentElement ) {
 
                jQuery.offset.initialize();
 
-               var offsetParent = elem.offsetParent, prevOffsetParent = elem,
-                       doc = elem.ownerDocument, computedStyle, docElem = doc.documentElement,
-                       body = doc.body, defaultView = doc.defaultView,
+               var computedStyle,
+                       offsetParent = elem.offsetParent,
+                       prevOffsetParent = elem,
+                       doc = elem.ownerDocument,
+                       docElem = doc.documentElement,
+                       body = doc.body,
+                       defaultView = doc.defaultView,
                        prevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,
-                       top = elem.offsetTop, left = elem.offsetLeft;
+                       top = elem.offsetTop,
+                       left = elem.offsetLeft;
 
                while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
                        if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) {
@@ -70,7 +89,7 @@ if ( "getBoundingClientRect" in document.documentElement ) {
                                top  += elem.offsetTop;
                                left += elem.offsetLeft;
 
-                               if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && /^t(able|d|h)$/i.test(elem.nodeName)) ) {
+                               if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {
                                        top  += parseFloat( computedStyle.borderTopWidth  ) || 0;
                                        left += parseFloat( computedStyle.borderLeftWidth ) || 0;
                                }
@@ -103,7 +122,7 @@ if ( "getBoundingClientRect" in document.documentElement ) {
 
 jQuery.offset = {
        initialize: function() {
-               var body = document.body, container = document.createElement("div"), innerDiv, checkDiv, table, td, bodyMarginTop = parseFloat( jQuery.curCSS(body, "marginTop", true) ) || 0,
+               var body = document.body, container = document.createElement("div"), innerDiv, checkDiv, table, td, bodyMarginTop = parseFloat( jQuery.css(body, "marginTop") ) || 0,
                        html = "<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";
 
                jQuery.extend( container.style, { position: "absolute", top: 0, left: 0, margin: 0, border: 0, width: "1px", height: "1px", visibility: "hidden" } );
@@ -137,37 +156,53 @@ jQuery.offset = {
        },
 
        bodyOffset: function( body ) {
-               var top = body.offsetTop, left = body.offsetLeft;
+               var top = body.offsetTop,
+                       left = body.offsetLeft;
 
                jQuery.offset.initialize();
 
                if ( jQuery.offset.doesNotIncludeMarginInBodyOffset ) {
-                       top  += parseFloat( jQuery.curCSS(body, "marginTop",  true) ) || 0;
-                       left += parseFloat( jQuery.curCSS(body, "marginLeft", true) ) || 0;
+                       top  += parseFloat( jQuery.css(body, "marginTop") ) || 0;
+                       left += parseFloat( jQuery.css(body, "marginLeft") ) || 0;
                }
 
                return { top: top, left: left };
        },
-       
+
        setOffset: function( elem, options, i ) {
+               var position = jQuery.css( elem, "position" );
+
                // set position first, in-case top/left are set even on static elem
-               if ( /static/.test( jQuery.curCSS( elem, "position" ) ) ) {
+               if ( position === "static" ) {
                        elem.style.position = "relative";
                }
-               var curElem   = jQuery( elem ),
+
+               var curElem = jQuery( elem ),
                        curOffset = curElem.offset(),
-                       curTop    = parseInt( jQuery.curCSS( elem, "top",  true ), 10 ) || 0,
-                       curLeft   = parseInt( jQuery.curCSS( elem, "left", true ), 10 ) || 0;
+                       curCSSTop = jQuery.css( elem, "top" ),
+                       curCSSLeft = jQuery.css( elem, "left" ),
+                       calculatePosition = (position === "absolute" && jQuery.inArray('auto', [curCSSTop, curCSSLeft]) > -1),
+                       props = {}, curPosition = {}, curTop, curLeft;
+
+               // need to be able to calculate position if either top or left is auto and position is absolute
+               if ( calculatePosition ) {
+                       curPosition = curElem.position();
+               }
+
+               curTop  = calculatePosition ? curPosition.top  : parseInt( curCSSTop,  10 ) || 0;
+               curLeft = calculatePosition ? curPosition.left : parseInt( curCSSLeft, 10 ) || 0;
 
                if ( jQuery.isFunction( options ) ) {
                        options = options.call( elem, i, curOffset );
                }
 
-               var props = {
-                       top:  (options.top  - curOffset.top)  + curTop,
-                       left: (options.left - curOffset.left) + curLeft
-               };
-               
+               if (options.top != null) {
+                       props.top = (options.top - curOffset.top) + curTop;
+               }
+               if (options.left != null) {
+                       props.left = (options.left - curOffset.left) + curLeft;
+               }
+
                if ( "using" in options ) {
                        options.using.call( elem, props );
                } else {
@@ -190,17 +225,17 @@ jQuery.fn.extend({
 
                // Get correct offsets
                offset       = this.offset(),
-               parentOffset = /^body|html$/i.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();
+               parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();
 
                // Subtract 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.curCSS(elem, "marginTop",  true) ) || 0;
-               offset.left -= parseFloat( jQuery.curCSS(elem, "marginLeft", true) ) || 0;
+               offset.top  -= parseFloat( jQuery.css(elem, "marginTop") ) || 0;
+               offset.left -= parseFloat( jQuery.css(elem, "marginLeft") ) || 0;
 
                // Add offsetParent borders
-               parentOffset.top  += parseFloat( jQuery.curCSS(offsetParent[0], "borderTopWidth",  true) ) || 0;
-               parentOffset.left += parseFloat( jQuery.curCSS(offsetParent[0], "borderLeftWidth", true) ) || 0;
+               parentOffset.top  += parseFloat( jQuery.css(offsetParent[0], "borderTopWidth") ) || 0;
+               parentOffset.left += parseFloat( jQuery.css(offsetParent[0], "borderLeftWidth") ) || 0;
 
                // Subtract the two offsets
                return {
@@ -212,7 +247,7 @@ jQuery.fn.extend({
        offsetParent: function() {
                return this.map(function() {
                        var offsetParent = this.offsetParent || document.body;
-                       while ( offsetParent && (!/^body|html$/i.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) {
+                       while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) {
                                offsetParent = offsetParent.offsetParent;
                        }
                        return offsetParent;
@@ -227,7 +262,7 @@ jQuery.each( ["Left", "Top"], function( i, name ) {
 
        jQuery.fn[ method ] = function(val) {
                var elem = this[0], win;
-               
+
                if ( !elem ) {
                        return null;
                }
@@ -260,9 +295,11 @@ jQuery.each( ["Left", "Top"], function( i, name ) {
 });
 
 function getWindow( elem ) {
-       return ("scrollTo" in elem && elem.document) ?
+       return jQuery.isWindow( elem ) ?
                elem :
                elem.nodeType === 9 ?
                        elem.defaultView || elem.parentWindow :
                        false;
 }
+
+})( jQuery );