var Popup = new function()
{
    this.show = function(popupId, innerHtml)
    {
        // initialize array for visible popups
        if (visiblePopups == null)
            visiblePopups = new Array();

        // get popup objects
        var maskObject = document.getElementById(popupId + '_mask');
        var iframeObject = document.getElementById(popupId + '_iframe');
        var wrapperObject = document.getElementById(popupId + '_wrapper');

        // if popup does not exist
        if (maskObject == null && iframeObject == null && wrapperObject == null)
        {
            // create the mask
            maskObject = document.createElement('div');
            maskObject.id = popupId + '_mask';
            maskObject.style.position = 'absolute';
            maskObject.style.left = 0;
            maskObject.style.top = 0;
            maskObject.style.width = documentWidth() + 'px';
            maskObject.style.height = documentHeight() + 'px';
            maskObject.style.opacity = '0.40';
            maskObject.style.filter = 'alpha(opacity=40)';
            maskObject.style.backgroundColor = '#000000';
            document.body.appendChild(maskObject);

            // create the iframe (only this will overlap "select" in IE)
            iframeObject = document.createElement('iframe');
            iframeObject.id = popupId + '_iframe';
            iframeObject.style.position = 'absolute';
            iframeObject.style.left = 0;
            iframeObject.style.top = 0;
            iframeObject.style.width = documentWidth() + 'px';
            iframeObject.style.height = documentHeight() + 'px';
            iframeObject.style.border = 'none';
            iframeObject.style.opacity = '0.00';
            iframeObject.style.filter = 'alpha(opacity=0)';
            iframeObject.src = 'about:blank';
            document.body.appendChild(iframeObject);

            // create the wrapper
            wrapperObject = document.createElement('div');
            wrapperObject.id = popupId + '_wrapper';
            wrapperObject.style.position = 'absolute';
            wrapperObject.style.left = 0;
            wrapperObject.style.top = 0;
            wrapperObject.innerHTML = innerHtml ? innerHtml : '';
            document.body.appendChild(wrapperObject);

            // update the coordinates
            updateCoordinates(popupId);

            // add the id to visible popups array
            visiblePopups[popupId] = popupId;

            // enable automatic update of popup coordinates
            // when window is resized or scrolled
            window.onresize = updateVisiblePopups;
            window.onscroll = updateVisiblePopups;
        }
        else
        {
            // if popup exists but is not complete
            // then recreate it
            if (maskObject == null || iframeObject == null || wrapperObject == null)
            {
                this.hide(popupId);
                this.show(popupId, innerHtml);
                return;
            }

            // hide the popup and move it to the top left corner
            wrapperObject.style.display = 'none';
            wrapperObject.style.left = 0;
            wrapperObject.style.top = 0;

            // update the content
            wrapperObject.innerHTML = innerHtml ? innerHtml : '';

            // show the popup
            wrapperObject.style.display = 'block';

            // update the coordinates
            updateCoordinates(popupId);
        }
    }

    this.hide = function(popupId)
    {
        // remove the id from visible popups array
        if (visiblePopups != null && visiblePopups[popupId] != null)
            visiblePopups[popupId] = null;

        // get popup elements
        var maskObject = document.getElementById(popupId + '_mask');
        var iframeObject = document.getElementById(popupId + '_iframe');
        var wrapperObject = document.getElementById(popupId + '_wrapper');

        // remove the wrapper
        if (wrapperObject != null)
            document.body.removeChild(wrapperObject);

        // remove the iframe
        if (iframeObject != null)
            document.body.removeChild(iframeObject);

        // remove the mask
        if (maskObject != null)
            document.body.removeChild(maskObject);

        // if there are not visible popups left
        // then disable automatic update of popup coordinates
        // when window is resized or scrolled
        if (visiblePopups.length == 0)
        {
            window.onresize = null;
            window.onscroll = null;
        }
    }

    function updateCoordinates(popupId)
    {
        // get popup elements
        var maskObject = document.getElementById(popupId + '_mask');
        var iframeObject = document.getElementById(popupId + '_iframe');
        var wrapperObject = document.getElementById(popupId + '_wrapper');

        // if the popup does not exist or is incomplete
        // then hide it
        if (maskObject == null || iframeObject == null || wrapperObject == null)
        {
            this.hide();
            return;
        }

        // calculate horizontal offset
        var offsetX = scrollXOffset() + clientWidth() > documentWidth() ?
                      documentWidth() - clientWidth() : scrollXOffset();

        // calculate vertical offset
        var offsetY = scrollYOffset() + clientHeight() > documentHeight() ?
                      documentHeight() - clientHeight() : scrollYOffset();

        maskObject.style.left = 0;
        maskObject.style.top = 0;
        maskObject.style.width = documentWidth() + 'px';
        maskObject.style.height = documentHeight() + 'px';

        // update the popup iframe
        iframeObject.style.left = 0;
        iframeObject.style.top = 0;
        iframeObject.style.width = documentWidth() + 'px';
        iframeObject.style.height = documentHeight() + 'px';

        // update the popup wrapper
        var x = Math.round((clientWidth() - wrapperObject.offsetWidth) / 2);
        var y = Math.round((clientHeight() - wrapperObject.offsetHeight) / 2);
        wrapperObject.style.left = x + offsetX + 'px';
        wrapperObject.style.top = y + offsetY + 'px';
    }

    function updateVisiblePopups()
    {
        // update coordinates of all visible popups
        for (var popupId in visiblePopups)
            updateCoordinates(popupId);
    }

    function clientWidth()
    {
        try
        {
            // get all possible values
            var tmp = new Array;
            tmp[0] = window.innerWidth ? window.innerWidth : 0;
            tmp[1] = document.documentElement ? document.documentElement.clientWidth : 0;

            // choose smallest nonzero value
            var width = tmp[0];

            for (var i = 1; i < tmp.length; i++)
            {
                if ((width == 0) || (tmp[i] > 0 && tmp[i] < width))
                    width = tmp[i];
            }

            return width;
        }
        catch (exception)
        {
            return 0;
        }
    }

    function clientHeight()
    {
        try
        {
            // get all possible values
            var tmp = new Array;
            tmp[0] = window.innerHeight ? window.innerHeight : 0;
            tmp[1] = document.documentElement ? document.documentElement.clientHeight : 0;

            // choose smallest nonzero value
            var height = tmp[0];

            for (var i = 1; i < tmp.length; i++)
            {
                if ((height == 0) || (tmp[i] > 0 && tmp[i] < height))
                    height = tmp[i];
            }

            return height;
        }
        catch (exception)
        {
            return 0;
        }
    }

    function documentWidth()
    {
        // return width of the document
        return Math.max(document.width ? document.width : 0,
                        document.documentElement.offsetWidth ? document.documentElement.offsetWidth : 0,
                        document.documentElement.scrollWidth ? document.documentElement.scrollWidth : 0,
                        document.body.offsetWidth ? document.body.offsetWidth : 0,
                        document.body.scrollWidth ? document.body.scrollWidth : 0,
                        clientWidth());
    }

    function documentHeight()
    {
        // return height of the document
        return Math.max(document.height ? document.height : 0,
                        document.documentElement.offsetHeight ? document.documentElement.offsetHeight : 0,
                        document.documentElement.scrollHeight ? document.documentElement.scrollHeight : 0,
                        document.body.offsetHeight ? document.body.offsetHeight : 0,
                        document.body.scrollHeight ? document.body.scrollHeight : 0,
                        clientHeight());
    }

    function scrollXOffset()
    {
        try
        {
            // get all possible values
            var tmp = new Array;
            tmp[0] = window.pageXOffset ? window.pageXOffset : 0;
            tmp[1] = document.documentElement ? document.documentElement.scrollLeft : 0;
            tmp[2] = document.body ? document.body.scrollLeft : 0;

            // choose smallest nonzero value
            var scrollXOffset = tmp[0];

            for (var i = 1; i < tmp.length; i++)
            {
                if ((scrollXOffset == 0) || (tmp[i] > 0 && tmp[i] < scrollXOffset))
                    scrollXOffset = tmp[i];
            }

            return scrollXOffset;
        }
        catch (exception)
        {
            return 0;
        }
    }

    function scrollYOffset()
    {
        try
        {
            // get all possible values
            var tmp = new Array;
            tmp[0] = window.pageYOffset ? window.pageYOffset : 0;
            tmp[1] = document.documentElement ? document.documentElement.scrollTop : 0;
            tmp[2] = document.body ? document.body.scrollTop : 0;

            // choose smallest nonzero value
            var scrollYOffset = tmp[0];

            for (var i = 1; i < tmp.length; i++)
            {
                if ((scrollYOffset == 0) || (tmp[i] > 0 && tmp[i] < scrollYOffset))
                    scrollYOffset = tmp[i];
            }

            return scrollYOffset;
        }
        catch (exception)
        {
            return 0;
        }
    }

    var visiblePopups;
}