﻿function ViewPortVars( /* optional */ container)
{
    //Container: The object that has the scroll bars attached to it (e.g. the browser window or a modal popup)
    //    - Defaults to browser window (i.e. the "viewport")
    this.container = container || window;
    this.isModalPopup = this.container != window;
}

ViewPortVars.prototype =
{
    x: function()
    {
        return nextQuery(this.container).scrollLeft();
    },
    y: function()
    {
        return nextQuery(this.container).scrollTop();
    },
    width: function()
    {
        return nextQuery(this.container).width();
    },
    height: function()
    {
        return nextQuery(this.container).height();
    },
    upperLeft: function()
    {
        return { X: this.x(), Y: this.y() };
    },
    upperRight: function()
    {
        return { X: this.x() + this.width(), Y: this.y() };
    },
    lowerLeft: function()
    {
        return { X: this.x(), Y: this.y() + this.height() };
    },
    lowerRight: function()
    {
        return { X: this.x() + this.width(), Y: this.y() + this.height() };
    },
    elementAreaOutsideViewPort: function(element)
    {
        var area = { Right: 0, Left: 0, Top: 0, Bottom: 0 };
        if (element)
        {
            var bounds = null;
            if (this.isModalPopup)
            {
                bounds = {
                    height: nextQuery(element).height(),
                    width: nextQuery(element).width(),
                    x: 0,
                    y: 0
                }
            }
            else
            {
                bounds = {
                    height: nextQuery(element).height(),
                    width: nextQuery(element).width(),
                    x: nextQuery(element).offset().left,
                    y: nextQuery(element).offset().top
                }
            }
            if (bounds.height <= 0 || bounds.width <= 0 || bounds.x < 0 || bounds.y < 0)
                return null;
            if (bounds.x + bounds.width > this.upperRight().X)
                area.Right = bounds.x + bounds.width - this.upperRight().X;
            if (this.upperLeft().X > bounds.x)
                area.Left = this.upperLeft().X - bounds.x;
            if (this.upperLeft().Y > bounds.y)
                area.Top = this.upperLeft().Y - bounds.y;
            if (bounds.y + bounds.height > this.lowerLeft().Y)
                area.Bottom = bounds.y + bounds.height - this.lowerLeft().Y;
        }
        if (area.Left > 0 || area.Right > 0 || area.Top > 0 || area.Bottom > 0)
            return area;
        else
            return null;
    },
    isOutsideViewPort: function(element)
    {
        return this.elementAreaOutsideViewPort(element) != null;
    },
    adjustElementSizeOnce: function(element)
    {
        if (!element)
            return;

        var actualHeight = nextQuery(element).height();
        var actualWidth = nextQuery(element).width();
        var scrollbarPadding = 15; //must allow for scroll bars + extra
        var maxHeight = this.height() - (2 * scrollbarPadding);
        var maxWidth = this.width() - (2 * scrollbarPadding);

        if (element.firstChild.id != "borderDiv")
        {
            var borderDiv = document.createElement("div");
            borderDiv.setAttribute("id", "borderDiv");
            while (element.childNodes.length > 0)
            {
                borderDiv.appendChild(element.firstChild);
            }
            nextQuery(borderDiv).height("100%");
            nextQuery(borderDiv).width("100%");
            nextQuery(borderDiv).css("overflow", "visible");
            element.appendChild(borderDiv);
            nextQuery(element).css("overflow", "auto");
        }

        //Using element.style.minHeight instead of nextQuery(element).css("min-height") because there's not a reliable way to
        //check if the min-height (or width) value has been set when using jquery. Just easier to use the built-in approach.
        if (element.style.minWidth)
        {
            nextQuery(element).width(element.style.minWidth);
            actualWidth = nextQuery(element).width();
        }
        if (element.style.minHeight)
        {
            nextQuery(element).height(element.style.minHeight);
            actualHeight = nextQuery(element).height();
        }

        //If height has room to scroll or is greater than the viewport then we need to adjust the height
        if (actualHeight < element.scrollHeight - scrollbarPadding || actualHeight > maxHeight)
        {
            actualHeight = nextQuery(element).height();
            actualWidth = nextQuery(element).width();
            if (element.scrollHeight > 0 && actualHeight < element.scrollHeight - scrollbarPadding)
            {
                actualHeight = element.scrollHeight;
            }
            if (actualHeight > maxHeight)
            {
                actualHeight = maxHeight;
            }
            if (actualHeight < element.scrollHeight - scrollbarPadding)
            {
                actualWidth += scrollbarPadding;
            }
            if (actualHeight > 0 && actualWidth > 0)
            {
                nextQuery(element).height(actualHeight);
                nextQuery(element).width(actualWidth);
            }
        }
        //If width has room to scroll or is greater than the viewport then we need to adjust the width
        if (actualWidth < element.scrollWidth - scrollbarPadding || actualWidth > maxWidth)
        {
            actualHeight = nextQuery(element).height();
            actualWidth = nextQuery(element).width();
            if (element.scrollWidth > 0 && actualWidth < element.scrollWidth - scrollbarPadding)
            {
                actualWidth = element.scrollWidth;
            }
            if (actualWidth > maxWidth)
            {
                actualWidth = maxWidth;
            }
            if (actualWidth < element.scrollWidth - scrollbarPadding)
            {
                actualHeight += scrollbarPadding;
            }
            if (actualHeight > 0 && actualWidth > 0)
            {
                nextQuery(element).height(actualHeight);
                nextQuery(element).width(actualWidth);
            }
        }
        //If height has room to scroll or is greater than the viewport then we need to adjust the height
        if (actualHeight < element.scrollHeight - scrollbarPadding || actualHeight > maxHeight)
        {
            actualHeight = nextQuery(element).height();
            actualWidth = nextQuery(element).width();
            if (element.scrollHeight > 0 && actualHeight < element.scrollHeight - scrollbarPadding)
            {
                actualHeight = element.scrollHeight;
            }
            if (actualHeight > maxHeight)
            {
                actualHeight = maxHeight;
            }
            if (actualHeight < element.scrollHeight - scrollbarPadding)
            {
                actualWidth += scrollbarPadding;
            }
            if (actualHeight > 0 && actualWidth > 0)
            {
                nextQuery(element).height(actualHeight);
                nextQuery(element).width(actualWidth);
            }
        }
        element.scrollTop = 0;
        element.scrollTop = 0;
    },
    adjustElementSize: function(element)
    {
        this.adjustElementSizeOnce(element);
        this.adjustElementSizeOnce(element);
    },
    positionPopup: function(element)
    {
        if (element)
        {
            this.adjustElementSize(element);
            var outsideArea = this.elementAreaOutsideViewPort(element);
            if (outsideArea)
            {
                var bounds = Sys.UI.DomElement.getBounds(element);
                var x = bounds.x;
                var y = bounds.y;
                var padding = 10;
                if (outsideArea.Left > 0)
                    x = bounds.x + outsideArea.Left + padding;
                else if (outsideArea.Right > 0)
                    x = bounds.x - outsideArea.Right - padding;

                if (outsideArea.Top > 0)
                    y = bounds.y + outsideArea.Top + padding;
                else if (outsideArea.Bottom > 0)
                    y = bounds.y - outsideArea.Bottom - padding;

                Sys.UI.DomElement.setLocation(element, x, y);
            }
        }
    }
}

var viewport = new ViewPortVars();