﻿/// <reference name="MicrosoftAjax.js"/>
/// <reference name="vnetlinkedlist.js"/>
/// <reference name="jquery-1.2.1.js"/>

// Copyright (c) Ralph Varjabedian http://varjabedian.net
//
// commonpopupsengine.js v 1.4.3
// A file containing an implementation of a popups engine
// Octobor 2008
// 
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

CommonPopupsEngine = new Object();
CommonPopupsEngine.stackCollections = new Array();
CommonPopupsEngine.globalChannelsStack = new StackClass();

// configuration
CommonPopupsEngine_startupZIndex = 1000;
CommonPopupsEngine_maxPopupCollectionElements = 10;
CommonPopupsEngine_useGlobalZIndex = true;
CommonPopupsEngine_onlyShowToplevelPopup = true;
// configuration

CommonPopupsEngine._AddedCollection = function(channel, popupCollectionObject)
{
    CommonPopupsEngine.globalChannelsStack.Push(channel);
}

CommonPopupsEngine._RemovedCollection = function(channel, popupCollectionObject)
{
    CommonPopupsEngine.globalChannelsStack.Pop();
}

CommonPopupsEngine.GetStackChannel = function(channel)
{
    if (channel == null)
        channel = CommonPopupsEngine.globalChannelsStack.Peek();
    if (channel == null)
        return null;
    if (typeof(CommonPopupsEngine.stackCollections[channel]) == "undefined")
        CommonPopupsEngine.stackCollections[channel] = new StackClass();
    return CommonPopupsEngine.stackCollections[channel];
}

CommonPopupsEngine_GlobalZIndex = 0;
CommonPopupsEngine.GetNextZIndex = function(channel)
{
    if (CommonPopupsEngine_useGlobalZIndex)
    {
        var reset = true;
        for (var i = 0; i < CommonPopupsEngine.stackCollections.length; i++)
        {
            if (CommonPopupsEngine.stackCollections[i] != null && 
                CommonPopupsEngine.stackCollections[i].GetCount() > 0)
            {
                reset = false;
                break;
            }
        }
        if (reset)
            CommonPopupsEngine_GlobalZIndex = 0;
            
        var zIndex = CommonPopupsEngine_startupZIndex + CommonPopupsEngine_GlobalZIndex;
        CommonPopupsEngine_GlobalZIndex += CommonPopupsEngine_maxPopupCollectionElements;
        return zIndex;
    }
    else
        return CommonPopupsEngine.GetStackChannel(channel).GetCount();    
}

CommonPopupsEngine.GetHtmlPopup = function(channel, popupHtml)
{
/// <summary>Adds an html contents popup</summary>
/// <param name="channel">The channel of the popup, use 0 if not sure</param>
/// <param name="popupHtml">The html of the element to popup, usually a div</param>
    return CallWhenReady(CommonPopupsEngine._GetHtmlPopup, channel, popupHtml);
}

CommonPopupsEngine._GetHtmlPopup = function(channel, popupHtml)
{
    var stack = CommonPopupsEngine.GetStackChannel(channel);
    
    var popupCollectionObject = new PopupCollectionClass(channel);
    
    var htmlPopupObject = new HtmlPopupClass(popupHtml);
    htmlPopupObject.mainPopup = true;
    popupCollectionObject.Add(htmlPopupObject);
    
    return popupCollectionObject.SubmitCollection();
}

CommonPopupsEngine.GetIFramePopup = function(channel, src, width, height, left, top, loadingOption) 
{
    /// <summary>Adds an html contents popup</summary>
    /// <param name="channel">The channel of the popup, use 0 if not sure</param>
    /// <param name="popupHtml">The html of the element to popup, usually a div</param>
    return CallWhenReady(CommonPopupsEngine._GetIFramePopup, channel, src, width, height, left, top, loadingOption);
}

CommonPopupsEngine._GetIFramePopup = function(channel, src, width, height, left, top, loadingOption) 
{
    var popupCollectionObject = new PopupCollectionClass(channel);

    // add the iframe popupHtml
    var iframePopupObject = new IFramePopupClass(src);
    popupCollectionObject.Add(iframePopupObject);
    popupCollectionObject.SetDimensions(left, top, width, height);
    iframePopupObject.mainPopup = true;

    if (loadingOption == 1)  // wait to load then show
    {
        popupCollectionObject.DisableShow();
        iframePopupObject.iframejqelement.load(
            function() 
            { 
                popupCollectionObject.EnableShow();
                popupCollectionObject.Show();
            });
    }
    else if (loadingOption == 2)  // with animation
    {
        var aniHtml = '<div style="background-image: url(/Images/waitanimation.gif);cursor:wait;background-repeat:no-repeat;background-position:center;border:solid 1px black;background-color:white;"></div>';
        var aniHtmlPopupObject = new HtmlPopupClass(aniHtml);

        popupCollectionObject.Add(aniHtmlPopupObject);

        iframePopupObject.iframejqelement.load(
            function() {aniHtmlPopupObject.CloseDialog();});
                
        iframePopupObject.SetFadeInDelay = function(delay)
        {   
            this.fadeInDelay = delay + 500;
        }
    }

    return popupCollectionObject.SubmitCollection();
}

CommonPopupsEngine.ShowElementPopup = function(channel, elementID)
{
/// <summary>Adds an html contents popup</summary>
/// <param name="channel">The channel of the popup, use 0 if not sure</param>
/// <param name="elementID">The elementID of the control to popup</param>
    return CallWhenReady(CommonPopupsEngine._ShowElementPopup, channel, elementID);
}

CommonPopupsEngine._ShowElementPopup = function(channel, elementID)
{
    var popupCollectionObject = new PopupCollectionClass(channel);
    
    var elementPopupObject = new ElementPopupClass(elementID);
    elementPopupObject.mainPopup = true;
    popupCollectionObject.Add(elementPopupObject);
    
    return popupCollectionObject.SubmitCollection();
}

CommonPopupsEngine.AddNewPopupCollection = function(popupCollectionObject)
{
    var stack = CommonPopupsEngine.GetStackChannel(popupCollectionObject.channel);

    if (CommonPopupsEngine_onlyShowToplevelPopup && stack.HasElements())
        stack.Peek().Hide();

    stack.Push(popupCollectionObject);
    CommonPopupsEngine._AddedCollection(popupCollectionObject.channel, popupCollectionObject);
    
    return popupCollectionObject;
}

CommonPopupsEngine.CloseTopmostPopupCollection = function(channel)
{
/// <summary>Closes the top most popup collection</summary>
/// <param name="channel">The channel of the popup collection. You can pass null here. If you pass null then the last active channel will be used</param>
    var stack = CommonPopupsEngine.GetStackChannel(channel);
    if (stack == null)
        return;
    
    var popupCollectionObject = stack.Peek();
    if (popupCollectionObject == null)
        return;
        
    if (popupCollectionObject._CloseDialogInternal())
    {
        stack.Pop();
        CommonPopupsEngine._RemovedCollection(channel, popupCollectionObject);
    }
    
    var i;
    for (i = 0; i < CommonPopupsEngine.stackCollections.length; i++)
    {
        if (typeof(CommonPopupsEngine.stackCollections[i]) != "undefined")
        {
            var stack1 = CommonPopupsEngine.stackCollections[i];
            while (stack1.HasElements())
            {
                popupCollectionObject = stack1.Peek();
                if (popupCollectionObject.HasPendingClose())
                {
                    popupCollectionObject._CloseDialogInternal();
                    stack1.Pop();
                    CommonPopupsEngine._RemovedCollection(channel, popupCollectionObject);
                }
                else
                    break;
            }
        }
    }
        
    if (CommonPopupsEngine_onlyShowToplevelPopup && stack.HasElements())
        stack.Peek().Show();
}

CommonPopupsEngine.GetPopupCollectionsCount = function(channel)
{
/// <summary>Closes the top most popup collection</summary>
/// <param name="channel">The channel of the popup collection, if you pass null then the last active channel will be used</param>
    var stack = CommonPopupsEngine.GetStackChannel(channel);
    if (stack == null)
        return 0;
    return stack.GetCount();
}

CommonPopupsEngine.GetTopmostPopupCollection = function(channel)
{
/// <summary>Gets the top most popup collection object</summary>
/// <param name="channel">The channel of the popup collection, if you pass null then the last active channel will be used</param>
    var stack = CommonPopupsEngine.GetStackChannel(channel);
    if (stack == null)
        return null;
    return stack.Peek();
}

PopupCollectionClass = function(channel)
{
    this.collectionLL = new LinkedListClass();
    this.pendingClose = false;
    this.closed = false;
    this.channel = channel;
    this._disableShow = false;
    this.startZIndex = CommonPopupsEngine.GetNextZIndex(channel);
}

PopupCollectionClass.prototype = 
{
    Add : function(htmlPopupObject)
    {
        if (htmlPopupObject.jqelement == null || htmlPopupObject.element == null)
            throw "Popup object should have jqelement,element defined";
        if (this.collectionLL.GetSize() == CommonPopupsEngine_maxPopupCollectionElements)
            throw "A popup collection has more elements than the max, please update CommonPopupsEngine_maxPopupCollectionElements";
        htmlPopupObject.popupCollection = this;
        this.collectionLL.Add(htmlPopupObject);
        return this;
    },
    
    InsertFirst : function(htmlPopupObject)
    {
        if (htmlPopupObject.jqelement == null || htmlPopupObject.element == null)
            throw "Popup object should have jqelement,element defined";
        if (this.collectionLL.GetSize() == CommonPopupsEngine_maxPopupCollectionElements)
            throw "A popup collection has more elements than the max, please update CommonPopupsEngine_maxPopupCollectionElements";
        this.collectionLL.GetListStart().InsertBefore(htmlPopupObject);
        htmlPopupObject.popupCollection = this;
        return this;
    },
    
    Count : function(htmlPopupObject)
    {
        return this.collectionLL.GetSize();
    },
    
    GetPopupsLinkedList : function()
    {
        return this.collectionLL;
    },
    
    foreach : function(statement)
    {
        var i;
        var ret = null;
        var node = this.collectionLL.GetListStart();
        while (node)
        {
            var ret1 = eval("node.object." + statement + ";");
            if (node == this.collectionLL.GetListStart())
                ret = ret1;
            else
            {
                if (ret != ret1)
                    throw "foreach statment in PopupCollectionClass returned different values for each element, they all must return the same";
            }
            ret = ret1;
            
            node = node.Next();
        }
        return ret;
    },
    
    Show : function()
    {
        this.foreach("Show();");
        return this;
    },
    
    Hide : function()
    {
        this.foreach("Hide();");
        return this;
    },
    
    SetFadeInDelay : function(delay)
    {
        this.foreach("SetFadeInDelay(" + delay + ");");
        return this;
    },
    
    SetFadeOutDelay : function(delay)
    {
        this.foreach("SetFadeOutDelay(" + delay + ");");
        return this;
    },
    
    ShowDialog : function()
    {
        // 1. set proper zindex
        var zindex = this.startZIndex;        
        var node = this.collectionLL.GetListStart();
        while (node)
        {
            var jqelement = node.object.jqelement;
            
            jqelement.css('position', 'absolute');
            jqelement.css('z-index', CommonPopupsEngine_startupZIndex +  zindex);
               
            zindex++;               
            node = node.Next();
        }        
        
        // 2. go over BeforeCreateDialog
        node = this.collectionLL.GetListStart();
        while (node)
        {
            if (node.object.BeforeCreateDialog != null)
                node.object.BeforeCreateDialog(this);
            
            node = node.Next();
        }        
        
        // 3. CreateDialog
        this.foreach("CreateDialog();");
        this.CreateDialogCalled = true;

        // 4. go over BeforeSetDimension
        node = this.collectionLL.GetListStart();
        while (node)
        {
            if (node.object.BeforeSetDimension != null)
                node.object.BeforeSetDimension(this);
            
            node = node.Next();
        }                
        
        // 5. go over SetDimension
        var x = null;
        var y = null;
        var width = null;
        var height = null;
        
        if (this.x != null)
            x = this.x;
        if (this.y != null)
            y = this.y;
        if (this.width != null)
            width = this.width;
        if (this.height != null)
            height = this.height;
        
        node = this.collectionLL.GetListStart();
        while (node)
        {
            node.object.SetDimensions(x, y, width, height);
            node = node.Next();
        }        

        // 4. go over BeforeInitialShow
        node = this.collectionLL.GetListStart();
        while (node)
        {
            if (node.object.BeforeInitialShow != null)
                node.object.BeforeInitialShow(this);
            
            node = node.Next();
        }                

        // 6. show dialog
        this.foreach("InitialShow();");
        this.InitialShowCalled = true;
        
        // 7. go over AfterInitialShow
        node = this.collectionLL.GetListStart();
        while (node)
        {
            if (node.object.AfterInitialShow != null)
                node.object.AfterInitialShow(this);
            node = node.Next();
        }        
        return this;
    },
    
    DisableShow : function()
    {
        this._disableShow = true;
        return this;
    },    
    
    EnableShow : function()
    {
        this._disableShow = false;
        return this;
    },    
    
    IsShowEnabled : function()
    {
        return !this._disableShow;
    },    
    
    CloseDialog : function()
    {
        if (CommonPopupsEngine.GetTopmostPopupCollection(this.channel) == this)
            CommonPopupsEngine.CloseTopmostPopupCollection(this.channel);
        else
            this.pendingClose = true;
        return true;
    },
    
    AutoCloseDialogAfter : function(milliSeconds)
    {
        if (milliSeconds <= 0)
            return this;
        var This = this;
        setTimeout(function(){ This.CloseDialog(); }, milliSeconds);
        return this;
    },
    
    SetDimensions : function(x, y, width, height)
    {
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
        if (this.InitialShowCalled == true)
        {
            var node = this.collectionLL.GetListStart();
            while (node)
            {
                node.object.SetDimensions(x, y, width, height);
                node = node.Next();
            }        
        }            
        return this;
    },
    
    _CloseDialogInternal : function()
    {
        this.pendingClose = false;
        this.closed = true;
        var node = this.collectionLL.GetListStart();
        while (node)
        {
            if (node.object.BeforeCloseDialog != null)
                node.object.BeforeCloseDialog(this);
            node = node.Next();
        }        
        var ret = this.foreach("CloseDialog();");
        node = this.collectionLL.GetListStart();
        while (node)
        {
            if (node.object.AfterCloseDialog != null)
                node.object.AfterCloseDialog(this);
            node = node.Next();
        }        
        return ret;
    },
    
    HasPendingClose : function()
    {
        return this.pendingClose;
    },
    
    SubmitCollection : function()
    {
        return CommonPopupsEngine.AddNewPopupCollection(this);
    },
    
    GetMainPopupOrTopmostPopup : function()
    {
        if (this.collectionLL.GetSize() == 0)
            return null;
        var node = this.collectionLL.GetListStart();
        while (node)
        {
            if (node.object.mainPopup == true) // sometimes in collections, one popup defines that it is the main one
                return node.object;
            node = node.Next();                
        }
        return this.collectionLL.GetListEnd().object;
    },
    
    MoveBy : function(xOffset, yOffset)
    {
        this.foreach("MoveBy(" + xOffset + "," + yOffset + ");");
        return this;        
    },
    
    __end : 0
}

var _CallWhenReady_IsReady = false;
$(document).ready(function() { _CallWhenReady_IsReady = true; $(document).keydown(OnKeyDown); });

OnKeyDown = function(e)
{
    var event = (e ? e : window.event);

    if (e.keyCode == 27)
    {
        setTimeout(function(){CommonPopupsEngine.CloseTopmostPopupCollection();}, 10);
        e.returnValue = false;
        e.cancelBubble = true;
        return false;
    }
}

function CallWhenReady(fn)
{
    var This = this;
    if (_CallWhenReady_IsReady)
    {
        var fnargs = new Array();
        for (var i = 1; i < CallWhenReady.arguments.length; i++)
            fnargs[i - 1] = arguments[i];
        return fn.apply(This, fnargs);
    }
    else
    {
        var args = CallWhenReady.arguments;
        setTimeout(function(){CallWhenReady.apply(This, args)}, 100);
        return null;
    }
}

BasePopupClass = function()
{
    this.fadeInDelay = 0;
    this.fadeOutDelay = 0;
}

BasePopupClass.prototype = 
{
    extend : function(obj)
    {
        for (var m in obj)
            this[m] = obj[m];
    },

    CreateDialog : function()
    {
        this.jqelement.appendTo($("body")).hide();
    },
    
    InitialShow : function()
    {
        if (this.IsShowEnabled())
            this.Show();
    },
    
    CloseDialog : function()
    {
        if (this.fadeOutDelay == 0)
            this.jqelement.remove();
        else
        {
            var jqelement = this.jqelement;
            this.jqelement.fadeOut(this.fadeOutDelay, function(){jqelement.remove();});
        }
        this.closed = true;
        return true;            
    },
    
    Show : function()
    {
        if (this.fadeInDelay == 0)
            this.jqelement.show();
        else
            this.jqelement.fadeIn(this.fadeInDelay);
    },
    
    Hide : function()
    {
        if (this.fadeOutDelay == 0)
            this.jqelement.hide();
        else
            this.jqelement.fadeOut(this.fadeOutDelay);
    },
    
    SetFadeInDelay : function(delay)
    {
        this.fadeInDelay = delay;
    },
    
    SetFadeOutDelay : function(delay)
    {
        this.fadeOutDelay = delay;
    },
    
    SetDimensions : function(x, y, width, height)
    {
        if (x != null)
            this.jqelement.css('left', x);
        if (y != null)                
            this.jqelement.css('top', y);    
        if (width != null)
            this.jqelement.css('width', width);
        if (height != null)
            this.jqelement.css('height', height);
    },
    
    IsShowEnabled : function()
    {
        return this.popupCollection.IsShowEnabled();
    },
    
    __showDisabled : false,
    
    MoveBy : function(xOffset, yOffset)
    {
        var x = parseInt(this.jqelement.css('left'));
        var y = parseInt(this.jqelement.css('top'));
        this.jqelement.css('left', x + xOffset);
        this.jqelement.css('top',  y + yOffset);
    },
    
    __end : 0
}

HtmlPopupClass_IDsCount = 0;
HtmlPopupClass = function(popupHtml)
{
    var newJQueryElement = $(popupHtml);
    if (typeof(newJQueryElement.attr('id')) == 'undefined')
    {
        newJQueryElement.attr('id', "HtmlPopup" + HtmlPopupClass_IDsCount);
        HtmlPopupClass_IDsCount++;
    }

    this.jqelement = newJQueryElement;
    
    var popupID = newJQueryElement.attr('id');
    newJQueryElement.get(0).htmlPopupObject = this;

    this.id = popupID;
    this.element = newJQueryElement.get(0);
    this.closed = false;
}
HtmlPopupClass.prototype = new BasePopupClass();

IFramePopupClass_IDsCount = 0;
IFramePopupClass = function(src)
{
    var html = "";
    html += "<div style='border: solid 1px black; background-color:white;'>";
    html +=     "<table border='0'>";
    html +=         "<tr><td align='right'><div style='margin-right:5px; margin-top:5px;'><img title='Close' src='/Images/x.png' style='background-color:blue; padding:2px; cursor: pointer;' onclick='CommonPopupsEngine.CloseTopmostPopupCollection(); return false;'/></div></td></tr>";
    html +=         "<tr><td align='center' valign='middle' style='vertical-align:middle;'>";
    html +=             "<iframe id='if" + IFramePopupClass_IDsCount + "' src='" + src + "' scrolling='no' frameborder='0' style='border:0;border-style:none;vertical-align:middle;'></iframe>";
    html +=         "</td></tr>";
    html += "</div>";

    var newJQueryElement = $(html);
    newJQueryElement.attr('id', "IFramePopup" + IFramePopupClass_IDsCount);
    
    var popupID = newJQueryElement.attr('id');
    var iframejqelement = newJQueryElement.find('#if' + IFramePopupClass_IDsCount);
    newJQueryElement.get(0).iframePopupObject = this;

    IFramePopupClass_IDsCount++;

    this.id = popupID;
    this.iframejqelement = iframejqelement;
    this.element = newJQueryElement.get(0);
    this.jqelement = newJQueryElement;
    this.closed = false;
}

IFramePopupClass.prototype = new BasePopupClass();
IFramePopupClass.prototype.extend( 
{
    SetDimensions : function(x, y, width, height)
    {
        this.jqelement.css('left', x);
        this.jqelement.css('top', y);    
        this.jqelement.css('width', width);
        this.jqelement.css('height', height);    

        width -= 5;
        height -= 30;
        
        this.iframejqelement.attr('width', width);
        this.iframejqelement.attr('height', height);
        this.iframejqelement.css('width', width);
        this.iframejqelement.css('height', height);
    },
    
    CloseDialog : function()
    {
        this.iframejqelement.load(function(){});
        this.iframejqelement.attr('src', '');
        if (this.fadeOutDelay == 0)
            this.jqelement.remove();
        else
        {
            var jqelement = this.jqelement;
            this.jqelement.fadeOut(this.fadeOutDelay, function(){jqelement.remove();});
        }
        this.closed = true;
        return true;            
    },
    
    __end : 0
});

ElementPopupClass_IDsCount = 0;
ElementPopupClass = function(elementID)
{
    var existingJQueryElement = $('#' +elementID);
    if (typeof(existingJQueryElement.attr('id')) == 'undefined')
    {
        existingJQueryElement.attr('id', "ElementPopup" + ElementPopupClass_IDsCount);
        ElementPopupClass_IDsCount++;
    }
    
    existingJQueryElement.get(0).elementPopupObject = this;

    this.id = elementID;
    this.element = existingJQueryElement.get(0);
    this.jqelement = existingJQueryElement;
    this.closed = false;
}

ElementPopupClass.prototype = new BasePopupClass();
ElementPopupClass.prototype.extend( 
{
    CreateDialog : function()
    {
        this.jqelement.hide();
        this.jqelement.css('visibility', 'visible');
    },
    
    CloseDialog : function()
    {
        this.Hide();
        this.closed = true;
        return true;            
    },
    
    __end : 0
});

PopupCollectionClass.prototype.AddGrayout = function(grayoutColor)
{
/// <summary>Adds a grayout on the popup collection</summary>
/// <param name="grayoutColor">The color of the grayout</param>
    grayoutColor = (grayoutColor == null) ? '#999999' : grayoutColor;
    var width  = getScrollWidth();
    var height = getScrollHeight();
    var grayoutHtml = '<div style="width:'+width+';height:'+height+'; position:fixed; background-color:' + grayoutColor + '; top:0;left:0;opacity:0.85;filter: Alpha(opacity=85)"></div>';
    var htmlPopupObject = new HtmlPopupClass(grayoutHtml);
    htmlPopupObject.SetDimensions = function(){}; // should not be changed
    htmlPopupObject.SetFadeInDelay = htmlPopupObject.SetDimensions;
    htmlPopupObject.SetFadeOutDelay = htmlPopupObject.SetDimensions;
    htmlPopupObject.MoveBy = htmlPopupObject.SetDimensions;
    this.InsertFirst(htmlPopupObject);
    return this;
}

PopupCollectionClass.prototype.AddShadow = function(shadowColor, margin)
{
/// <summary>Adds a shadow behind the top popup element, this should be called first in the Chaining of functions</summary>
/// <param name="shadowColor">The color of the shadow</param>
/// <param name="margin">The margin in pixels of how much the shadow would cast</param>
    margin = (margin == null) ? 6 : margin;
    shadowColor = (shadowColor == null) ? 'black' : shadowColor;
    var shadowHtml = '<div style="background-color:' + shadowColor + ';opacity:0.2;filter: Alpha(opacity=20)"></div>';
    var htmlPopupObject = new HtmlPopupClass(shadowHtml);
    htmlPopupObject.margin = margin;
    htmlPopupObject.SetDimensions = function(x, y, width, height){};
    htmlPopupObject.SetFadeOutDelay = function() {}
    htmlPopupObject.InitialShow = function() {},
    htmlPopupObject.AfterInitialShow = function(popupCollection)
    {
        // set up proper dimensions for the shadow
        var topjqElement = popupCollection.GetMainPopupOrTopmostPopup().jqelement;
        this.jqelement.css('width',  topjqElement.width());
        this.jqelement.css('height', topjqElement.height());
        var top = topjqElement.css('top');
        var left = topjqElement.css('left');
        if (top != 'auto' && left != 'auto')
        {
            top  = parseInt(top.replace('px', ''));
            left = parseInt(left.replace('px', ''));
            this.jqelement.css('top',  top + this.margin);
            this.jqelement.css('left', left + this.margin);
        }
        if (this.IsShowEnabled())
            this.Show();
    }
    this.InsertFirst(htmlPopupObject);
    return this;
}

var EnableUserPositioning_CurrentPopupCollectionDragging = null;
PopupCollectionClass.prototype.EnableUserPositioning = function()
{
/// <summary>Enabled the popup collection to be moved by the user by dragging</summary>
    var mainjqElement = this.GetMainPopupOrTopmostPopup().jqelement;
    var popupCollection = this;
    
    this.GetMainPopupOrTopmostPopup().BeforeCloseDialog = function() 
        { mainjqElement.unbind('mousedown'); }
    
    mainjqElement.bind('mousedown', function(e)
    {
        var event = (e == null ? window.event : e);
        EnableUserPositioning_CurrentPopupCollectionDragging = popupCollection;
        
		popupCollection.lastMouseDownX = event.clientX;
		popupCollection.lastMouseDownY = event.clientY;
		
		$("body").unbind('mousemove', EnableUserPositioning_MouseMove);
	    $("body").bind('mousemove', EnableUserPositioning_MouseMove)
	    
	    $("body").unbind('mouseup', EnableUserPositioning_MouseUp);
        $("body").bind('mouseup', EnableUserPositioning_MouseUp);
	        	
	    $("body").css('cursor', 'move');
    });
    return this;
}

function EnableUserPositioning_MouseMove(e)
{
    if (EnableUserPositioning_CurrentPopupCollectionDragging == null)
        return;
        
    var event = (e == null ? window.event : e);
    
    var xOffset = event.clientX - EnableUserPositioning_CurrentPopupCollectionDragging.lastMouseDownX;
    var yOffset = event.clientY - EnableUserPositioning_CurrentPopupCollectionDragging.lastMouseDownY;
    EnableUserPositioning_CurrentPopupCollectionDragging.lastMouseDownX = event.clientX;
    EnableUserPositioning_CurrentPopupCollectionDragging.lastMouseDownY = event.clientY;
    EnableUserPositioning_CurrentPopupCollectionDragging.MoveBy(xOffset, yOffset);
}

function EnableUserPositioning_MouseUp(e)
{
    $("body").unbind('mouseup');
    $("body").unbind('mousemove');
    $("body").css('cursor', 'default');
    EnableUserPositioning_CurrentPopupCollectionDragging = null;
}

PopupCollectionClass.prototype.Center = function(method)
{
/// <summary>Sets the dimensions so that it is centered</summary>
    var popupCollection = this;
    
    var mainjqElement = this.GetMainPopupOrTopmostPopup().jqelement;
    // we need proper event handling for these overrides
    var oldFn = this.GetMainPopupOrTopmostPopup().BeforeSetDimension;
    this.GetMainPopupOrTopmostPopup().BeforeSetDimension = function()
    {
        mainjqElement.css('opacity', '0');
        mainjqElement.css('filter', 'Alpha(opacity=0)');
        mainjqElement.show();
        var width  = popupCollection.width  ? popupCollection.width  : mainjqElement.width();
        var height = popupCollection.height ? popupCollection.height : mainjqElement.height();
        mainjqElement.hide();
        mainjqElement.css('opacity', '1');
        mainjqElement.css('filter', 'Alpha(opacity=100)');
        
        if (method == CommonPopupsEngine.CenterVertical)
        {
            popupCollection.SetDimensions(
                null, 
                (getWindowHeight()/2 - height/2) + getYScrollOffset(), 
                popupCollection.width, 
                popupCollection.height);
        }
        else if (method == CommonPopupsEngine.CenterHorizontal)
        {
            popupCollection.SetDimensions(
                (getWindowWidth()/2  - width /2) + getXScrollOffset(), 
                null, 
                popupCollection.width, 
                popupCollection.height);
        }
        else
        {
            popupCollection.SetDimensions(
                (getWindowWidth()/2  - width /2) + getXScrollOffset(), 
                (getWindowHeight()/2 - height/2) + getYScrollOffset(), 
                popupCollection.width, 
                popupCollection.height);
        }
            
        if (oldFn != null)
            oldFn();            
    }
    return this;
}

CommonPopupsEngine.CenterBoth = null;
CommonPopupsEngine.CenterVertical = 1;
CommonPopupsEngine.CenterHorizontal = 2;

function getXScrollOffset()
{
    return (window.pageXOffset ? window.pageXOffset : (document.body.scrollLeft ? document.body.scrollLeft : 
        (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : 0)));
}

function getYScrollOffset()
{
    return (window.pageYOffset ? window.pageYOffset : (document.body.scrollTop ? document.body.scrollTop : 
        (document.documentElement.scrollTop ? document.documentElement.scrollTop : 0)));
}

function getWindowWidth()
{
    return (window.innerWidth ? window.innerWidth : (document.documentElement.clientWidth ? document.documentElement.clientWidth : 
        (document.body.clientWidth ? document.body.clientWidth : 0)));
}

function getWindowHeight()
{
    return (window.innerHeight ? window.innerHeight : (document.documentElement.clientHeight ? document.documentElement.clientHeight : 
        (document.body.clientHeight ? document.body.clientHeight : 0)));
}

function getScrollWidth()
{
	return document.all ? Math.max(Math.max(document.documentElement.offsetWidth, 
	    document.documentElement.scrollWidth), document.body.scrollWidth) : 
	    (document.body ? document.body.scrollWidth : ((document.documentElement.scrollWidth != 0) ? 
	    document.documentElement.scrollWidth : 0));
}
 
function getScrollHeight()
{
	return document.all ? Math.max(Math.max(document.documentElement.offsetHeight, 
	    document.documentElement.scrollHeight), Math.max(document.body.offsetHeight, 
	    document.body.scrollHeight)) : (document.body ? document.body.scrollHeight : 
	    ((document.documentElement.scrollHeight != 0) ? document.documentElement.scrollHeight : 0));
}
