home *** CD-ROM | disk | FTP | other *** search
/ PC Active 2009 March / PCA223.ISO / Software / tuneup / TU2008TrialNL.exe / ie_jquery.dimensions.js50 < prev    next >
Encoding:
Text File  |  2008-05-27  |  23.4 KB  |  655 lines

  1. /* Copyright (c) 2007 Paul Bakaus (paul.bakaus@googlemail.com) and Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)
  2.  * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
  3.  * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
  4.  *
  5.  * $LastChangedDate: 2007-08-17 13:14:11 -0500 (Fri, 17 Aug 2007) $
  6.  * $Rev: 2759 $
  7.  *
  8.  * Version: 1.1.2
  9.  *
  10.  * Requires: jQuery 1.1.3+
  11.  */
  12.  
  13. (function($){
  14.  
  15. // store a copy of the core height and width methods
  16. var height = $.fn.height,
  17.     width  = $.fn.width;
  18.  
  19. $.fn.extend({
  20.     /**
  21.      * If used on document, returns the document's height (innerHeight).
  22.      * If used on window, returns the viewport's (window) height.
  23.      * See core docs on height() to see what happens when used on an element.
  24.      *
  25.      * @example $("#testdiv").height()
  26.      * @result 200
  27.      *
  28.      * @example $(document).height()
  29.      * @result 800
  30.      *
  31.      * @example $(window).height()
  32.      * @result 400
  33.      *
  34.      * @name height
  35.      * @type Number
  36.      * @cat Plugins/Dimensions
  37.      */
  38.     height: function() {
  39.         if ( !this[0] ) error();
  40.         if ( this[0] == window )
  41.             if ( $.browser.opera || ($.browser.safari && parseInt($.browser.version) > 520) )
  42.                 return self.innerHeight - (($(document).height() > self.innerHeight) ? getScrollbarWidth() : 0);
  43.             else if ( $.browser.safari )
  44.                 return self.innerHeight;
  45.             else
  46.                 return $.boxModel && document.documentElement.clientHeight || document.body.clientHeight;
  47.         
  48.         if ( this[0] == document ) 
  49.             return Math.max( ($.boxModel && document.documentElement.scrollHeight || document.body.scrollHeight), document.body.offsetHeight );
  50.         
  51.         return height.apply(this, arguments);
  52.     },
  53.     
  54.     /**
  55.      * If used on document, returns the document's width (innerWidth).
  56.      * If used on window, returns the viewport's (window) width.
  57.      * See core docs on width() to see what happens when used on an element.
  58.      *
  59.      * @example $("#testdiv").width()
  60.      * @result 200
  61.      *
  62.      * @example $(document).width()
  63.      * @result 800
  64.      *
  65.      * @example $(window).width()
  66.      * @result 400
  67.      *
  68.      * @name width
  69.      * @type Number
  70.      * @cat Plugins/Dimensions
  71.      */
  72.     width: function() {
  73.         if (!this[0]) error();
  74.         if ( this[0] == window )
  75.             if ( $.browser.opera || ($.browser.safari && parseInt($.browser.version) > 520) )
  76.                 return self.innerWidth - (($(document).width() > self.innerWidth) ? getScrollbarWidth() : 0);
  77.             else if ( $.browser.safari )
  78.                 return self.innerWidth;
  79.             else
  80.                 return $.boxModel && document.documentElement.clientWidth || document.body.clientWidth;
  81.  
  82.         if ( this[0] == document )
  83.             if ($.browser.mozilla) {
  84.                 // mozilla reports scrollWidth and offsetWidth as the same
  85.                 var scrollLeft = self.pageXOffset;
  86.                 self.scrollTo(99999999, self.pageYOffset);
  87.                 var scrollWidth = self.pageXOffset;
  88.                 self.scrollTo(scrollLeft, self.pageYOffset);
  89.                 return document.body.offsetWidth + scrollWidth;
  90.             }
  91.             else 
  92.                 return Math.max( (($.boxModel && !$.browser.safari) && document.documentElement.scrollWidth || document.body.scrollWidth), document.body.offsetWidth );
  93.  
  94.         return width.apply(this, arguments);
  95.     },
  96.     
  97.     /**
  98.      * Gets the inner height (excludes the border and includes the padding) for the first matched element.
  99.      * If used on document, returns the document's height (innerHeight).
  100.      * If used on window, returns the viewport's (window) height.
  101.      *
  102.      * @example $("#testdiv").innerHeight()
  103.      * @result 210
  104.      *
  105.      * @name innerHeight
  106.      * @type Number
  107.      * @cat Plugins/Dimensions
  108.      */
  109.     innerHeight: function() {
  110.         if (!this[0]) error();
  111.         return this[0] == window || this[0] == document ?
  112.             this.height() :
  113.             this.is(':visible') ?
  114.                 this[0].offsetHeight - num(this, 'borderTopWidth') - num(this, 'borderBottomWidth') :
  115.                 this.height() + num(this, 'paddingTop') + num(this, 'paddingBottom');
  116.     },
  117.     
  118.     /**
  119.      * Gets the inner width (excludes the border and includes the padding) for the first matched element.
  120.      * If used on document, returns the document's width (innerWidth).
  121.      * If used on window, returns the viewport's (window) width.
  122.      *
  123.      * @example $("#testdiv").innerWidth()
  124.      * @result 210
  125.      *
  126.      * @name innerWidth
  127.      * @type Number
  128.      * @cat Plugins/Dimensions
  129.      */
  130.     innerWidth: function() {
  131.         if (!this[0]) error();
  132.         return this[0] == window || this[0] == document ?
  133.             this.width() :
  134.             this.is(':visible') ?
  135.                 this[0].offsetWidth - num(this, 'borderLeftWidth') - num(this, 'borderRightWidth') :
  136.                 this.width() + num(this, 'paddingLeft') + num(this, 'paddingRight');
  137.     },
  138.     
  139.     /**
  140.      * Gets the outer height (includes the border and padding) for the first matched element.
  141.      * If used on document, returns the document's height (innerHeight).
  142.      * If used on window, returns the viewport's (window) height.
  143.      *
  144.      * The margin can be included in the calculation by passing an options map with margin
  145.      * set to true.
  146.      *
  147.      * @example $("#testdiv").outerHeight()
  148.      * @result 220
  149.      *
  150.      * @example $("#testdiv").outerHeight({ margin: true })
  151.      * @result 240
  152.      *
  153.      * @name outerHeight
  154.      * @type Number
  155.      * @param Map options Optional settings to configure the way the outer height is calculated.
  156.      * @cat Plugins/Dimensions
  157.      */
  158.     outerHeight: function(options) {
  159.         if (!this[0]) error();
  160.         options = $.extend({ margin: false }, options || {});
  161.         return this[0] == window || this[0] == document ?
  162.             this.height() :
  163.             this.is(':visible') ?
  164.                 this[0].offsetHeight + (options.margin ? (num(this, 'marginTop') + num(this, 'marginBottom')) : 0) :
  165.                 this.height() 
  166.                     + num(this,'borderTopWidth') + num(this, 'borderBottomWidth') 
  167.                     + num(this, 'paddingTop') + num(this, 'paddingBottom')
  168.                     + (options.margin ? (num(this, 'marginTop') + num(this, 'marginBottom')) : 0);
  169.     },
  170.     
  171.     /**
  172.      * Gets the outer width (including the border and padding) for the first matched element.
  173.      * If used on document, returns the document's width (innerWidth).
  174.      * If used on window, returns the viewport's (window) width.
  175.      *
  176.      * The margin can be included in the calculation by passing an options map with margin
  177.      * set to true.
  178.      *
  179.      * @example $("#testdiv").outerWidth()
  180.      * @result 1000
  181.      *
  182.      * @example $("#testdiv").outerWidth({ margin: true })
  183.      * @result 1020
  184.      * 
  185.      * @name outerHeight
  186.      * @type Number
  187.      * @param Map options Optional settings to configure the way the outer width is calculated.
  188.      * @cat Plugins/Dimensions
  189.      */
  190.     outerWidth: function(options) {
  191.         if (!this[0]) error();
  192.         options = $.extend({ margin: false }, options || {});
  193.         return this[0] == window || this[0] == document ?
  194.             this.width() :
  195.             this.is(':visible') ?
  196.                 this[0].offsetWidth + (options.margin ? (num(this, 'marginLeft') + num(this, 'marginRight')) : 0) :
  197.                 this.width() 
  198.                     + num(this, 'borderLeftWidth') + num(this, 'borderRightWidth') 
  199.                     + num(this, 'paddingLeft') + num(this, 'paddingRight')
  200.                     + (options.margin ? (num(this, 'marginLeft') + num(this, 'marginRight')) : 0);
  201.     },
  202.     
  203.     /**
  204.      * Gets how many pixels the user has scrolled to the right (scrollLeft).
  205.      * Works on containers with overflow: auto and window/document.
  206.      *
  207.      * @example $(window).scrollLeft()
  208.      * @result 100
  209.      *
  210.      * @example $(document).scrollLeft()
  211.      * @result 100
  212.      * 
  213.      * @example $("#testdiv").scrollLeft()
  214.      * @result 100
  215.      *
  216.      * @name scrollLeft
  217.      * @type Number
  218.      * @cat Plugins/Dimensions
  219.      */
  220.     /**
  221.      * Sets the scrollLeft property for each element and continues the chain.
  222.      * Works on containers with overflow: auto and window/document.
  223.      *
  224.      * @example $(window).scrollLeft(100).scrollLeft()
  225.      * @result 100
  226.      * 
  227.      * @example $(document).scrollLeft(100).scrollLeft()
  228.      * @result 100
  229.      *
  230.      * @example $("#testdiv").scrollLeft(100).scrollLeft()
  231.      * @result 100
  232.      *
  233.      * @name scrollLeft
  234.      * @param Number value A positive number representing the desired scrollLeft.
  235.      * @type jQuery
  236.      * @cat Plugins/Dimensions
  237.      */
  238.     scrollLeft: function(val) {
  239.         if (!this[0]) error();
  240.         if ( val != undefined )
  241.             // set the scroll left
  242.             return this.each(function() {
  243.                 if (this == window || this == document)
  244.                     window.scrollTo( val, $(window).scrollTop() );
  245.                 else
  246.                     this.scrollLeft = val;
  247.             });
  248.         
  249.         // return the scroll left offest in pixels
  250.         if ( this[0] == window || this[0] == document )
  251.             return self.pageXOffset ||
  252.                 $.boxModel && document.documentElement.scrollLeft ||
  253.                 document.body.scrollLeft;
  254.                 
  255.         return this[0].scrollLeft;
  256.     },
  257.     
  258.     /**
  259.      * Gets how many pixels the user has scrolled to the bottom (scrollTop).
  260.      * Works on containers with overflow: auto and window/document.
  261.      *
  262.      * @example $(window).scrollTop()
  263.      * @result 100
  264.      *
  265.      * @example $(document).scrollTop()
  266.      * @result 100
  267.      * 
  268.      * @example $("#testdiv").scrollTop()
  269.      * @result 100
  270.      *
  271.      * @name scrollTop
  272.      * @type Number
  273.      * @cat Plugins/Dimensions
  274.      */
  275.     /**
  276.      * Sets the scrollTop property for each element and continues the chain.
  277.      * Works on containers with overflow: auto and window/document.
  278.      *
  279.      * @example $(window).scrollTop(100).scrollTop()
  280.      * @result 100
  281.      * 
  282.      * @example $(document).scrollTop(100).scrollTop()
  283.      * @result 100
  284.      *
  285.      * @example $("#testdiv").scrollTop(100).scrollTop()
  286.      * @result 100
  287.      *
  288.      * @name scrollTop
  289.      * @param Number value A positive number representing the desired scrollTop.
  290.      * @type jQuery
  291.      * @cat Plugins/Dimensions
  292.      */
  293.     scrollTop: function(val) {
  294.         if (!this[0]) error();
  295.         if ( val != undefined )
  296.             // set the scroll top
  297.             return this.each(function() {
  298.                 if (this == window || this == document)
  299.                     window.scrollTo( $(window).scrollLeft(), val );
  300.                 else
  301.                     this.scrollTop = val;
  302.             });
  303.         
  304.         // return the scroll top offset in pixels
  305.         if ( this[0] == window || this[0] == document )
  306.             return self.pageYOffset ||
  307.                 $.boxModel && document.documentElement.scrollTop ||
  308.                 document.body.scrollTop;
  309.  
  310.         return this[0].scrollTop;
  311.     },
  312.     
  313.     /** 
  314.      * Gets the top and left positioned offset in pixels.
  315.      * The positioned offset is the offset between a positioned
  316.      * parent and the element itself.
  317.      *
  318.      * For accurate calculations make sure to use pixel values for margins, borders and padding.
  319.      *
  320.      * @example $("#testdiv").position()
  321.      * @result { top: 100, left: 100 }
  322.      *
  323.      * @example var position = {};
  324.      * $("#testdiv").position(position)
  325.      * @result position = { top: 100, left: 100 }
  326.      * 
  327.      * @name position
  328.      * @param Object returnObject Optional An object to store the return value in, so as not to break the chain. If passed in the
  329.      *                            chain will not be broken and the result will be assigned to this object.
  330.      * @type Object
  331.      * @cat Plugins/Dimensions
  332.      */
  333.     position: function(returnObject) {
  334.         return this.offset({ margin: false, scroll: false, relativeTo: this.offsetParent() }, returnObject);
  335.     },
  336.     
  337.     /**
  338.      * Gets the location of the element in pixels from the top left corner of the viewport.
  339.      * The offset method takes an optional map of key value pairs to configure the way
  340.      * the offset is calculated. Here are the different options.
  341.      *
  342.      * (Boolean) margin - Should the margin of the element be included in the calculations? True by default.
  343.      * (Boolean) border - Should the border of the element be included in the calculations? False by default. 
  344.      * (Boolean) padding - Should the padding of the element be included in the calculations? False by default. 
  345.      * (Boolean) scroll - Should the scroll offsets of the parent elements be included in the calculations? True by default.
  346.      *                    When true it adds the total scroll offsets of all parents to the total offset and also adds two
  347.      *                    properties to the returned object, scrollTop and scrollLeft.
  348.      * (Boolean) lite - When true it will use the offsetLite method instead of the full-blown, slower offset method. False by default.
  349.      *                  Only use this when margins, borders and padding calculations don't matter.
  350.      * (HTML Element) relativeTo - This should be a parent of the element and should have position (like absolute or relative).
  351.      *                             It will retreive the offset relative to this parent element. By default it is the body element.
  352.      *
  353.      * Also an object can be passed as the second paramater to
  354.      * catch the value of the return and continue the chain.
  355.      *
  356.      * For accurate calculations make sure to use pixel values for margins, borders and padding.
  357.      * 
  358.      * Known issues:
  359.      *  - Issue: A div positioned relative or static without any content before it and its parent will report an offsetTop of 0 in Safari
  360.      *    Workaround: Place content before the relative div ... and set height and width to 0 and overflow to hidden
  361.      *
  362.      * @example $("#testdiv").offset()
  363.      * @result { top: 100, left: 100, scrollTop: 10, scrollLeft: 10 }
  364.      *
  365.      * @example $("#testdiv").offset({ scroll: false })
  366.      * @result { top: 90, left: 90 }
  367.      *
  368.      * @example var offset = {}
  369.      * $("#testdiv").offset({ scroll: false }, offset)
  370.      * @result offset = { top: 90, left: 90 }
  371.      *
  372.      * @name offset
  373.      * @param Map options Optional settings to configure the way the offset is calculated.
  374.      * @param Object returnObject An object to store the return value in, so as not to break the chain. If passed in the
  375.      *                            chain will not be broken and the result will be assigned to this object.
  376.      * @type Object
  377.      * @cat Plugins/Dimensions
  378.      */
  379.     offset: function(options, returnObject) {
  380.         if (!this[0]) error();
  381.         var x = 0, y = 0, sl = 0, st = 0,
  382.             elem = this[0], parent = this[0], op, parPos, elemPos = $.css(elem, 'position'),
  383.             mo = $.browser.mozilla, ie = $.browser.msie, oa = $.browser.opera,
  384.             sf = $.browser.safari, sf3 = $.browser.safari && parseInt($.browser.version) > 520,
  385.             absparent = false, relparent = false, 
  386.             options = $.extend({ margin: true, border: false, padding: false, scroll: true, lite: false, relativeTo: document.body }, options || {});
  387.         
  388.         // Use offsetLite if lite option is true
  389.         if (options.lite) return this.offsetLite(options, returnObject);
  390.         // Get the HTMLElement if relativeTo is a jquery collection
  391.         if (options.relativeTo.jquery) options.relativeTo = options.relativeTo[0];
  392.         
  393.         if (elem.tagName == 'BODY') {
  394.             // Safari 2 is the only one to get offsetLeft and offsetTop properties of the body "correct"
  395.             // Except they all mess up when the body is positioned absolute or relative
  396.             x = elem.offsetLeft;
  397.             y = elem.offsetTop;
  398.             // Mozilla ignores margin and subtracts border from body element
  399.             if (mo) {
  400.                 x += num(elem, 'marginLeft') + (num(elem, 'borderLeftWidth')*2);
  401.                 y += num(elem, 'marginTop')  + (num(elem, 'borderTopWidth') *2);
  402.             } else
  403.             // Opera ignores margin
  404.             if (oa) {
  405.                 x += num(elem, 'marginLeft');
  406.                 y += num(elem, 'marginTop');
  407.             } else
  408.             // IE does not add the border in Standards Mode
  409.             if ((ie && jQuery.boxModel)) {
  410.                 x += num(elem, 'borderLeftWidth');
  411.                 y += num(elem, 'borderTopWidth');
  412.             } else
  413.             // Safari 3 doesn't not include border or margin
  414.             if (sf3) {
  415.                 x += num(elem, 'marginLeft') + num(elem, 'borderLeftWidth');
  416.                 y += num(elem, 'marginTop')  + num(elem, 'borderTopWidth');
  417.             }
  418.         } else {
  419.             do {
  420.                 parPos = $.css(parent, 'position');
  421.             
  422.                 x += parent.offsetLeft;
  423.                 y += parent.offsetTop;
  424.  
  425.                 // Mozilla and IE do not add the border
  426.                 // Mozilla adds the border for table cells
  427.                 if ((mo && !parent.tagName.match(/^t[d|h]$/i)) || ie || sf3) {
  428.                     // add borders to offset
  429.                     x += num(parent, 'borderLeftWidth');
  430.                     y += num(parent, 'borderTopWidth');
  431.  
  432.                     // Mozilla does not include the border on body if an element isn't positioned absolute and is without an absolute parent
  433.                     if (mo && parPos == 'absolute') absparent = true;
  434.                     // IE does not include the border on the body if an element is position static and without an absolute or relative parent
  435.                     if (ie && parPos == 'relative') relparent = true;
  436.                 }
  437.  
  438.                 op = parent.offsetParent || document.body;
  439.                 if (options.scroll || mo) {
  440.                     do {
  441.                         if (options.scroll) {
  442.                             // get scroll offsets
  443.                             sl += parent.scrollLeft;
  444.                             st += parent.scrollTop;
  445.                         }
  446.                         
  447.                         // Opera sometimes incorrectly reports scroll offset for elements with display set to table-row or inline
  448.                         if (oa && ($.css(parent, 'display') || '').match(/table-row|inline/)) {
  449.                             sl = sl - ((parent.scrollLeft == parent.offsetLeft) ? parent.scrollLeft : 0);
  450.                             st = st - ((parent.scrollTop == parent.offsetTop) ? parent.scrollTop : 0);
  451.                         }
  452.                 
  453.                         // Mozilla does not add the border for a parent that has overflow set to anything but visible
  454.                         if (mo && parent != elem && $.css(parent, 'overflow') != 'visible') {
  455.                             x += num(parent, 'borderLeftWidth');
  456.                             y += num(parent, 'borderTopWidth');
  457.                         }
  458.                 
  459.                         parent = parent.parentNode;
  460.                     } while (parent != op);
  461.                 }
  462.                 parent = op;
  463.                 
  464.                 // exit the loop if we are at the relativeTo option but not if it is the body or html tag
  465.                 if (parent == options.relativeTo && !(parent.tagName == 'BODY' || parent.tagName == 'HTML'))  {
  466.                     // Mozilla does not add the border for a parent that has overflow set to anything but visible
  467.                     if (mo && parent != elem && $.css(parent, 'overflow') != 'visible') {
  468.                         x += num(parent, 'borderLeftWidth');
  469.                         y += num(parent, 'borderTopWidth');
  470.                     }
  471.                     // Safari 2 and opera includes border on positioned parents
  472.                     if ( ((sf && !sf3) || oa) && parPos != 'static' ) {
  473.                         x -= num(op, 'borderLeftWidth');
  474.                         y -= num(op, 'borderTopWidth');
  475.                     }
  476.                     break;
  477.                 }
  478.                 if (parent.tagName == 'BODY' || parent.tagName == 'HTML') {
  479.                     // Safari 2 and IE Standards Mode doesn't add the body margin for elments positioned with static or relative
  480.                     if (((sf && !sf3) || (ie && $.boxModel)) && elemPos != 'absolute' && elemPos != 'fixed') {
  481.                         x += num(parent, 'marginLeft');
  482.                         y += num(parent, 'marginTop');
  483.                     }
  484.                     // Safari 3 does not include the border on body
  485.                     // Mozilla does not include the border on body if an element isn't positioned absolute and is without an absolute parent
  486.                     // IE does not include the border on the body if an element is positioned static and without an absolute or relative parent
  487.                     if ( sf3 || (mo && !absparent && elemPos != 'fixed') || 
  488.                          (ie && elemPos == 'static' && !relparent) ) {
  489.                         x += num(parent, 'borderLeftWidth');
  490.                         y += num(parent, 'borderTopWidth');
  491.                     }
  492.                     break; // Exit the loop
  493.                 }
  494.             } while (parent);
  495.         }
  496.  
  497.         var returnValue = handleOffsetReturn(elem, options, x, y, sl, st);
  498.  
  499.         if (returnObject) { $.extend(returnObject, returnValue); return this; }
  500.         else              { return returnValue; }
  501.     },
  502.     
  503.     /**
  504.      * Gets the location of the element in pixels from the top left corner of the viewport.
  505.      * This method is much faster than offset but not as accurate when borders and margins are
  506.      * on the element and/or its parents. This method can be invoked
  507.      * by setting the lite option to true in the offset method.
  508.      * The offsetLite method takes an optional map of key value pairs to configure the way
  509.      * the offset is calculated. Here are the different options.
  510.      *
  511.      * (Boolean) margin - Should the margin of the element be included in the calculations? True by default.
  512.      * (Boolean) border - Should the border of the element be included in the calculations? False by default. 
  513.      * (Boolean) padding - Should the padding of the element be included in the calcuations? False by default. 
  514.      * (Boolean) scroll - Sould the scroll offsets of the parent elements be included int he calculations? True by default.
  515.      *                    When true it adds the total scroll offsets of all parents to the total offset and also adds two
  516.      *                    properties to the returned object, scrollTop and scrollLeft.
  517.      * (HTML Element) relativeTo - This should be a parent of the element and should have position (like absolute or relative).
  518.      *                             It will retreive the offset relative to this parent element. By default it is the body element.
  519.      *
  520.      * @name offsetLite
  521.      * @param Map options Optional settings to configure the way the offset is calculated.
  522.      * @param Object returnObject An object to store the return value in, so as not to break the chain. If passed in the
  523.      *                            chain will not be broken and the result will be assigned to this object.
  524.      * @type Object
  525.      * @cat Plugins/Dimensions
  526.      */
  527.     offsetLite: function(options, returnObject) {
  528.         if (!this[0]) error();
  529.         var x = 0, y = 0, sl = 0, st = 0, parent = this[0], offsetParent, 
  530.             options = $.extend({ margin: true, border: false, padding: false, scroll: true, relativeTo: document.body }, options || {});
  531.                 
  532.         // Get the HTMLElement if relativeTo is a jquery collection
  533.         if (options.relativeTo.jquery) options.relativeTo = options.relativeTo[0];
  534.         
  535.         do {
  536.             x += parent.offsetLeft;
  537.             y += parent.offsetTop;
  538.  
  539.             offsetParent = parent.offsetParent || document.body;
  540.             if (options.scroll) {
  541.                 // get scroll offsets
  542.                 do {
  543.                     sl += parent.scrollLeft;
  544.                     st += parent.scrollTop;
  545.                     parent = parent.parentNode;
  546.                 } while(parent != offsetParent);
  547.             }
  548.             parent = offsetParent;
  549.         } while (parent && parent.tagName != 'BODY' && parent.tagName != 'HTML' && parent != options.relativeTo);
  550.  
  551.         var returnValue = handleOffsetReturn(this[0], options, x, y, sl, st);
  552.  
  553.         if (returnObject) { $.extend(returnObject, returnValue); return this; }
  554.         else              { return returnValue; }
  555.     },
  556.     
  557.     /**
  558.      * Returns a jQuery collection with the positioned parent of 
  559.      * the first matched element. This is the first parent of 
  560.      * the element that has position (as in relative or absolute).
  561.      *
  562.      * @name offsetParent
  563.      * @type jQuery
  564.      * @cat Plugins/Dimensions
  565.      */
  566.     offsetParent: function() {
  567.         if (!this[0]) error();
  568.         var offsetParent = this[0].offsetParent;
  569.         while ( offsetParent && (offsetParent.tagName != 'BODY' && $.css(offsetParent, 'position') == 'static') )
  570.             offsetParent = offsetParent.offsetParent;
  571.         return $(offsetParent);
  572.     }
  573. });
  574.  
  575. /**
  576.  * Throws an error message when no elements are in the jQuery collection
  577.  * @private
  578.  */
  579. var error = function() {
  580.     throw "Dimensions: jQuery collection is empty";
  581. };
  582.  
  583. /**
  584.  * Handles converting a CSS Style into an Integer.
  585.  * @private
  586.  */
  587. var num = function(el, prop) {
  588.     return parseInt($.css(el.jquery?el[0]:el,prop))||0;
  589. };
  590.  
  591. /**
  592.  * Handles the return value of the offset and offsetLite methods.
  593.  * @private
  594.  */
  595. var handleOffsetReturn = function(elem, options, x, y, sl, st) {
  596.     if ( !options.margin ) {
  597.         x -= num(elem, 'marginLeft');
  598.         y -= num(elem, 'marginTop');
  599.     }
  600.  
  601.     // Safari and Opera do not add the border for the element
  602.     if ( options.border && (($.browser.safari && parseInt($.browser.version) < 520) || $.browser.opera) ) {
  603.         x += num(elem, 'borderLeftWidth');
  604.         y += num(elem, 'borderTopWidth');
  605.     } else if ( !options.border && !(($.browser.safari && parseInt($.browser.version) < 520) || $.browser.opera) ) {
  606.         x -= num(elem, 'borderLeftWidth');
  607.         y -= num(elem, 'borderTopWidth');
  608.     }
  609.  
  610.     if ( options.padding ) {
  611.         x += num(elem, 'paddingLeft');
  612.         y += num(elem, 'paddingTop');
  613.     }
  614.     
  615.     // do not include scroll offset on the element ... opera sometimes reports scroll offset as actual offset
  616.     if ( options.scroll && (!$.browser.opera || elem.offsetLeft != elem.scrollLeft && elem.offsetTop != elem.scrollLeft) ) {
  617.         sl -= elem.scrollLeft;
  618.         st -= elem.scrollTop;
  619.     }
  620.  
  621.     return options.scroll ? { top: y - st, left: x - sl, scrollTop:  st, scrollLeft: sl }
  622.                           : { top: y, left: x };
  623. };
  624.  
  625. /**
  626.  * Gets the width of the OS scrollbar
  627.  * @private
  628.  */
  629. var scrollbarWidth = 0;
  630. var getScrollbarWidth = function() {
  631.     if (!scrollbarWidth) {
  632.         var testEl = $('<div>')
  633.                 .css({
  634.                     width: 100,
  635.                     height: 100,
  636.                     overflow: 'auto',
  637.                     position: 'absolute',
  638.                     top: -1000,
  639.                     left: -1000
  640.                 })
  641.                 .appendTo('body');
  642.         scrollbarWidth = 100 - testEl
  643.             .append('<div>')
  644.             .find('div')
  645.                 .css({
  646.                     width: '100%',
  647.                     height: 200
  648.                 })
  649.                 .width();
  650.         testEl.remove();
  651.     }
  652.     return scrollbarWidth;
  653. };
  654.  
  655. })(jQuery);