if ( document.documentElement["getBoundingClientRect"] ) jQuery.fn.offset = function() { if ( !this[0] ) return { top: 0, left: 0 }; if ( this[0] === this[0].ownerDocument.body ) return jQuery.offset.bodyOffset( this[0] ); var box = this[0].getBoundingClientRect(), doc = this[0].ownerDocument, body = doc.body, docElem = doc.documentElement, clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0, top = box.top + (self.pageYOffset || jQuery.boxModel && docElem.scrollTop || body.scrollTop ) - clientTop, left = box.left + (self.pageXOffset || jQuery.boxModel && docElem.scrollLeft || body.scrollLeft) - clientLeft; return { top: top, left: left }; }; else jQuery.fn.offset = function() { if ( !this[0] ) return { top: 0, left: 0 }; if ( this[0] === this[0].ownerDocument.body ) return jQuery.offset.bodyOffset( this[0] ); jQuery.offset.initialized || jQuery.offset.initialize(); var elem = this[0], offsetParent = elem.offsetParent, prevOffsetParent = elem, doc = elem.ownerDocument, computedStyle, docElem = doc.documentElement, body = doc.body, defaultView = doc.defaultView, prevComputedStyle = defaultView.getComputedStyle(elem, null), top = elem.offsetTop, left = elem.offsetLeft; while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) { computedStyle = defaultView.getComputedStyle(elem, null); top -= elem.scrollTop, left -= elem.scrollLeft; if ( elem === offsetParent ) { top += elem.offsetTop, left += elem.offsetLeft; if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && /^t(able|d|h)$/i.test(elem.tagName)) ) top += parseInt( computedStyle.borderTopWidth, 10) || 0, left += parseInt( computedStyle.borderLeftWidth, 10) || 0; prevOffsetParent = offsetParent, offsetParent = elem.offsetParent; } if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" ) top += parseInt( computedStyle.borderTopWidth, 10) || 0, left += parseInt( computedStyle.borderLeftWidth, 10) || 0; prevComputedStyle = computedStyle; } if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" ) top += body.offsetTop, left += body.offsetLeft; if ( prevComputedStyle.position === "fixed" ) top += Math.max(docElem.scrollTop, body.scrollTop), left += Math.max(docElem.scrollLeft, body.scrollLeft); return { top: top, left: left }; }; jQuery.offset = { initialize: function() { if ( this.initialized ) return; var body = document.body, container = document.createElement('div'), innerDiv, checkDiv, table, td, rules, prop, bodyMarginTop = body.style.marginTop, html = '
'; rules = { position: 'absolute', top: 0, left: 0, margin: 0, border: 0, width: '1px', height: '1px', visibility: 'hidden' }; for ( prop in rules ) container.style[prop] = rules[prop]; container.innerHTML = html; body.insertBefore(container, body.firstChild); innerDiv = container.firstChild, checkDiv = innerDiv.firstChild, td = innerDiv.nextSibling.firstChild.firstChild; this.doesNotAddBorder = (checkDiv.offsetTop !== 5); this.doesAddBorderForTableAndCells = (td.offsetTop === 5); innerDiv.style.overflow = 'hidden', innerDiv.style.position = 'relative'; this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5); body.style.marginTop = '1px'; this.doesNotIncludeMarginInBodyOffset = (body.offsetTop === 0); body.style.marginTop = bodyMarginTop; body.removeChild(container); this.initialized = true; }, bodyOffset: function(body) { jQuery.offset.initialized || jQuery.offset.initialize(); var top = body.offsetTop, left = body.offsetLeft; if ( jQuery.offset.doesNotIncludeMarginInBodyOffset ) top += parseInt( jQuery.curCSS(body, 'marginTop', true), 10 ) || 0, left += parseInt( jQuery.curCSS(body, 'marginLeft', true), 10 ) || 0; return { top: top, left: left }; } }; jQuery.fn.extend({ position: function() { var left = 0, top = 0, results; if ( this[0] ) { // Get *real* offsetParent var offsetParent = this.offsetParent(), // Get correct offsets offset = this.offset(), parentOffset = /^body|html$/i.test(offsetParent[0].tagName) ? { 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 -= num( this, 'marginTop' ); offset.left -= num( this, 'marginLeft' ); // Add offsetParent borders parentOffset.top += num( offsetParent, 'borderTopWidth' ); parentOffset.left += num( offsetParent, 'borderLeftWidth' ); // Subtract the two offsets results = { top: offset.top - parentOffset.top, left: offset.left - parentOffset.left }; } return results; }, offsetParent: function() { var offsetParent = this[0].offsetParent || document.body; while ( offsetParent && (!/^body|html$/i.test(offsetParent.tagName) && jQuery.css(offsetParent, 'position') == 'static') ) offsetParent = offsetParent.offsetParent; return jQuery(offsetParent); } }); // Create scrollLeft and scrollTop methods jQuery.each( ['Left', 'Top'], function(i, name) { var method = 'scroll' + name; jQuery.fn[ method ] = function(val) { if (!this[0]) return null; return val !== undefined ? // Set the scroll offset this.each(function() { this == window || this == document ? window.scrollTo( !i ? val : jQuery(window).scrollLeft(), i ? val : jQuery(window).scrollTop() ) : this[ method ] = val; }) : // Return the scroll offset this[0] == window || this[0] == document ? self[ i ? 'pageYOffset' : 'pageXOffset' ] || jQuery.boxModel && document.documentElement[ method ] || document.body[ method ] : this[0][ method ]; }; });