Make sure that we don't attempt to handle scrolling when the node is disconnected...
[jquery.git] / src / offset.js
index c472f98..b94faf3 100644 (file)
@@ -1,8 +1,11 @@
 (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 ) { 
                        return this.each(function( i ) {
@@ -18,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,
@@ -72,7 +84,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;
                                }
@@ -207,7 +219,7 @@ 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
@@ -229,7 +241,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;
@@ -277,7 +289,7 @@ 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 :