/** 

 * This plugin overrides jQuery's height() and width() functions and

 * adds more handy stuff for cross-browser compatibility.

/**

 * Returns the css height value for the first matched element.

 * If used on document, returns the document's height (innerHeight)

 * If used on window, returns the viewport's (window) height

 *

 * @example $("#testdiv").height()

 * @result "200px"

 *

 * @example $(document).height();

 * @result 800

 *

 * @example $(window).height();

 * @result 400

 * 

 * @name height

 * @type Object

 * @cat Plugins/Dimensions

 */

jQuery.fn.height = function() {

    if ( this.get(0) == window )

        return self.innerHeight ||

            jQuery.boxModel && document.documentElement.clientHeight ||

            document.body.clientHeight;

    

    if ( this.get(0) == document )

        return Math.max( document.body.scrollHeight, document.body.offsetHeight );

    

    return this.css("height", arguments[0]);

};



/**

 * Returns the css width value for the first matched element.

 * If used on document, returns the document's width (innerWidth)

 * If used on window, returns the viewport's (window) width

 *

 * @example $("#testdiv").width()

 * @result "200px"

 *

 * @example $(document).width();

 * @result 800

 *

 * @example $(window).width();

 * @result 400

 * 

 * @name width

 * @type Object

 * @cat Plugins/Dimensions

 */

jQuery.fn.width = function() {

    if ( this.get(0) == window )

        return self.innerWidth ||

            jQuery.boxModel && document.documentElement.clientWidth ||

            document.body.clientWidth;

    

    if ( this.get(0) == document )

        return Math.max( document.body.scrollWidth, document.body.offsetWidth );

    

    return this.css("width", arguments[0]);

};



/**

 * Returns the inner height value (without border) for the first matched element.

 * If used on document, returns the document's height (innerHeight)

 * If used on window, returns the viewport's (window) height

 *

 * @example $("#testdiv").innerHeight()

 * @result 800

 * 

 * @name innerHeight

 * @type Number

 * @cat Plugins/Dimensions

 */

jQuery.fn.innerHeight = function() {

    return this.get(0) == window || this.get(0) == document ?

        this.height() :

        this.get(0).offsetHeight - parseInt(this.css("borderTop") || 0) - parseInt(this.css("borderBottom") || 0);

};



/**

 * Returns the inner width value (without border) for the first matched element.

 * If used on document, returns the document's Width (innerWidth)

 * If used on window, returns the viewport's (window) width

 *

 * @example $("#testdiv").innerWidth()

 * @result 1000

 * 

 * @name innerWidth

 * @type Number

 * @cat Plugins/Dimensions

 */

jQuery.fn.innerWidth = function() {

    return this.get(0) == window || this.get(0) == document ?

        this.width() :

        this.get(0).offsetWidth - parseInt(this.css("borderLeft") || 0) - parseInt(this.css("borderRight") || 0);

};



/**

 * Returns the outer height value (including border) for the first matched element.

 * Cannot be used on document or window.

 *

 * @example $("#testdiv").outerHeight()

 * @result 1000

 * 

 * @name outerHeight

 * @type Number

 * @cat Plugins/Dimensions

 */

jQuery.fn.outerHeight = function() {

    return this.get(0) == window || this.get(0) == document ?

        this.height() :

        this.get(0).offsetHeight;    

};



/**

 * Returns the outer width value (including border) for the first matched element.

 * Cannot be used on document or window.

 *

 * @example $("#testdiv").outerWidth()

 * @result 1000

 * 

 * @name outerWidth

 * @type Number

 * @cat Plugins/Dimensions

 */

jQuery.fn.outerWidth = function() {

    return this.get(0) == window || this.get(0) == document ?

        this.width() :

        this.get(0).offsetWidth;    

};



/**

 * Returns how many pixels the user has scrolled to the right (scrollLeft).

 * Works on containers with overflow: auto and window/document.

 *

 * @example $("#testdiv").scrollLeft()

 * @result 100

 * 

 * @name scrollLeft

 * @type Number

 * @cat Plugins/Dimensions

 */

jQuery.fn.scrollLeft = function() {

    if ( this.get(0) == window || this.get(0) == document )

        return self.pageXOffset ||

            jQuery.boxModel && document.documentElement.scrollLeft ||

            document.body.scrollLeft;

    

    return this.get(0).scrollLeft;

};



/**

 * Returns how many pixels the user has scrolled to the bottom (scrollTop).

 * Works on containers with overflow: auto and window/document.

 *

 * @example $("#testdiv").scrollTop()

 * @result 100

 * 

 * @name scrollTop

 * @type Number

 * @cat Plugins/Dimensions

 */

jQuery.fn.scrollTop = function() {

    if ( this.get(0) == window || this.get(0) == document )

        return self.pageYOffset ||

            jQuery.boxModel && document.documentElement.scrollTop ||

            document.body.scrollTop;



    return this.get(0).scrollTop;

};



/**

 * This returns an object with top, left, width, height, borderLeft,

 * borderTop, marginLeft, marginTop, scrollLeft, scrollTop, 

 * pageXOffset, pageYOffset.

 *

 * The top and left values include the scroll offsets but the

 * scrollLeft and scrollTop properties of the returned object

 * are the combined scroll offets of the parent elements 

 * (not including the window scroll offsets). This is not the

 * same as the element's scrollTop and scrollLeft.

 * 

 * For accurate readings make sure to use pixel values.

 *

 * @name offset    

 * @type Object

 * @cat Plugins/Dimensions

 * @author Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)

 */

/**

 * This returns an object with top, left, width, height, borderLeft,

 * borderTop, marginLeft, marginTop, scrollLeft, scrollTop, 

 * pageXOffset, pageYOffset.

 *

 * The top and left values include the scroll offsets but the

 * scrollLeft and scrollTop properties of the returned object

 * are the combined scroll offets of the parent elements 

 * (not including the window scroll offsets). This is not the

 * same as the element's scrollTop and scrollLeft.

 * 

 * For accurate readings make sure to use pixel values.

 *

 * @name offset    

 * @type Object

 * @param String refElement This is an expression. The offset returned will be relative to the first matched element.

 * @cat Plugins/Dimensions

 * @author Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)

 */

/**

 * This returns an object with top, left, width, height, borderLeft,

 * borderTop, marginLeft, marginTop, scrollLeft, scrollTop, 

 * pageXOffset, pageYOffset.

 *

 * The top and left values include the scroll offsets but the

 * scrollLeft and scrollTop properties of the returned object

 * are the combined scroll offets of the parent elements 

 * (not including the window scroll offsets). This is not the

 * same as the element's scrollTop and scrollLeft.

 * 

 * For accurate readings make sure to use pixel values.

 *

 * @name offset    

 * @type Object

 * @param jQuery refElement The offset returned will be relative to the first matched element.

 * @cat Plugins/Dimensions

 * @author Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)

 */

/**

 * This returns an object with top, left, width, height, borderLeft,

 * borderTop, marginLeft, marginTop, scrollLeft, scrollTop, 

 * pageXOffset, pageYOffset.

 *

 * The top and left values include the scroll offsets but the

 * scrollLeft and scrollTop properties of the returned object

 * are the combined scroll offets of the parent elements 

 * (not including the window scroll offsets). This is not the

 * same as the element's scrollTop and scrollLeft.

 * 

 * For accurate readings make sure to use pixel values.

 *

 * @name offset    

 * @type Object

 * @param HTMLElement refElement The offset returned will be relative to this element.

 * @cat Plugins/Dimensions

 * @author Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)

 */

jQuery.fn.offset = function(refElem) {

    if (!this[0]) throw 'jQuery.fn.offset requires an element.';



    refElem = (refElem) ? jQuery(refElem)[0] : null;

    var x = 0, y = 0, elem = this[0], parent = this[0], sl = 0, st = 0;

    do {

        if (parent.tagName == 'BODY' || parent.tagName == 'HTML') {

            // Safari and IE don't add margin for static and relative

            if ((jQuery.browser.safari || jQuery.browser.msie) && jQuery.css(parent, 'position') != 'absolute') {

                x += parseInt(jQuery.css(parent, 'marginLeft')) || 0;

                y += parseInt(jQuery.css(parent, 'marginTop'))  || 0;

            }

            break;

        }



        x += parent.offsetLeft || 0;

        y += parent.offsetTop  || 0;



        // Mozilla and IE do not add the border

        if (jQuery.browser.mozilla || jQuery.browser.msie) {

            x += parseInt(jQuery.css(parent, 'borderLeftWidth')) || 0;

            y += parseInt(jQuery.css(parent, 'borderTopWidth'))  || 0;

        }



        // Mozilla removes the border if the parent has overflow hidden

        if (jQuery.browser.mozilla && jQuery.css(parent, 'overflow') == 'hidden') {

            x += parseInt(jQuery.css(parent, 'borderLeftWidth')) || 0;

            y += parseInt(jQuery.css(parent, 'borderTopWidth'))  || 0;

        }



        // Need to get scroll offsets in-between offsetParents

        var op = parent.offsetParent;

        do {

            sl += parent.scrollLeft || 0;

            st += parent.scrollTop  || 0;

            parent = parent.parentNode;

        } while (parent != op);

    } while (parent);



    if (refElem) { // Get the relative offset

        var offset = jQuery(refElem).offset();

        x  = x  - offset.left;

        y  = y  - offset.top;

        sl = sl - offset.scrollLeft;

        st = st - offset.scrollTop;

    }



    // Safari and Opera do not add the border for the element

    if (jQuery.browser.safari || jQuery.browser.opera) {

        x += parseInt(jQuery.css(elem, 'borderLeftWidth')) || 0;

        y += parseInt(jQuery.css(elem, 'borderTopWidth'))  || 0;

    }



    return {

        top:  y - st,

        left: x - sl,

        width:  elem.offsetWidth,

        height: elem.offsetHeight,

        borderTop:  parseInt(jQuery.css(elem, 'borderTopWidth'))  || 0,

        borderLeft: parseInt(jQuery.css(elem, 'borderLeftWidth')) || 0,

        marginTop:  parseInt(jQuery.css(elem, 'marginTopWidth'))  || 0,

        marginLeft: parseInt(jQuery.css(elem, 'marginLeftWidth')) || 0,

        scrollTop:  st,

        scrollLeft: sl,

        pageYOffset: window.pageYOffset || document.documentElement.scrollTop  || document.body.scrollTop  || 0,

        pageXOffset: window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0

    };

};