// JScript File
// needs core.js

var nonModals = []


function NotifyOpener(msg, closeMe) {

    //this is a modal-side function
    //(this script is included in both the host and modal/modeless window)
    
    //modaless win will contain this script and a call to this method (spit out by way of NonModalDialogRedirect.AddNotifyOpenerScript() verb method)
    //if it wants to send a message to the host (opener) window - like the CSS editor telling the page designer to "refresh"
    
    //Opener must contain an OnPopUpNotify() funtion to recieve the message.
    
    //Theme Palette has one to get refresh messages from CSS editor, theme designer then uses this to to postback
    //to himself that the CSS has changed.
    try {
        if (typeof(window.opener) != 'undefined') {
            if (window.opener){
                if (window.opener.PopUpNotify) {
                    setTimeout("window.opener.PopUpNotify('" + msg + "')",100);
                }
            }else{
                NotifyFailure(msg);
            }
        }
        else if (typeof (BLACKBAUD.netcommunity.baseWindow) != 'undefined') {
            //hack for IE modal window launching not storing window.opener
            if (BLACKBAUD.netcommunity.baseWindow) {
                if (BLACKBAUD.netcommunity.baseWindow.PopUpNotify) {
                    setTimeout("BLACKBAUD.netcommunity.baseWindow.PopUpNotify('" + msg + "')", 100);
                }
            }else{
                NotifyFailure(msg);
            }
        }

        //alert(closeMe)
        if (typeof (closeMe) != 'undefined') {
            if (closeMe) {
                setTimeout("window.close()", 500);
            }
        }
    } catch (e) {
        NotifyFailure(msg);
    };
}

function NotifyFailure(msg) {
    if (msg == 'refresh') {
        alert('The browser window or tab that opened this dialog is no longer available, so it can not be refreshed automatically. Your changes have been saved but this dialog will now close.');
        window.close();
    }
}

function PopUpNotify(msg) {

    //This is an Opener-side function
    //(this script is included in both the host and modal/modeless window)

    //Opener window must contain its own OnPopupNotify() function if it wants to recieve/process the message
    //from the modal itself in a more custom way than just a "refresh" 
    if (window.OnPopUpNotify) {
        window.OnPopUpNotify(msg);
        return;
    }

    //otherwise just refresh opener page, if the message is "refresh"
    switch (msg) {
        case 'refresh':
            setTimeout(CoreModalReloadPage, 200);
        case 'postback':
            setTimeout(CoreModalPostbackPage, 200);
    }

}

function CoreModalReloadPage() {
    window.location=window.location.href;
}

function CoreModalPostbackPage() {
    if (__doPostBack) {
        __doPostBack('', '');
    } else {
        window.location = window.location.href;
    }    
}


function ShowNonModalDialogRedirectVerb(url, PostbackJS, OnCompleteFunctionName, windowFeatures, height, width, windowName, openFromTop) {

    // This is an Opener-side function
    // (this script is included in both the host and modal/modeless window)
    // a call to this is spit out by the NonModalDialogRedirect verb, usually attached to a button
    
    //windowFeatures = "height=400, menubar=no, resizable=yes, status=no, toolbar=no, width=600"

    if(typeof(windowFeatures)=='string'){
        windowFeatures = ConvertModalFeatures(windowFeatures, height, width)
    }

    var winOpener = window.top

    if (typeof (nonModals[windowName]) != 'undefined') {
        if (window.focus) {
            if (!nonModals[windowName].closed) {
                nonModals[windowName].focus();
                return;
            }
        }
    }
    
    var win = winOpener.open(url, windowName, windowFeatures);
    
    if (win == null)
	    throw new Error(-1,"window has been blocked");

	nonModals[windowName] = win;
	
	if (window.focus) {
	    win.focus();
	}
}

function showModalDialogRedirectVerb(URL, PostbackJS, OnCompleteFunctionName, windowFeatures, height, width, PostbackArg, externalCallbackFunction) {

    //externalCallbackFunction - is used by the API. Allows api users to provide a callback function and our internal callback to still be in the loop
    // api usage provides the internal callbacks found in api.js (e.g. ApiEditPartCallback()). 
    // So far this is only being used for the
    // PartEditButton api server control...
    
    if (!OnCompleteFunctionName)
        OnCompleteFunctionName = 'DefaultOnModalComplete'
    
    var dialogArguments = {};
    dialogArguments.PostbackJS = PostbackJS;
    dialogArguments.OnCompleteFunctionName = OnCompleteFunctionName;
    dialogArguments.PostbackArg = PostbackArg;
    dialogArguments.ExternalCallbackFunction = externalCallbackFunction;


    ModalDialogManager.openModal(URL, dialogArguments, windowFeatures, CompleteModalCall, height, width)

    // no return value (because sometimes it blocks and sometimes it doesn't)
}

function CompleteModalCall(ret) {
    // process return value and call desired completion function
    var cmd = ''

    jQuery(document.body).css('cursor', 'default');
    
    // true modal we have the return value now    
    if (typeof(ret) != 'undefined') {
        if (typeof(ret.CMD) == 'undefined'){
            // modal did not set the eventArgument - default to cancel
            // contentcontrols should pass this down via the AddDialogCloseScript call
            cmd = "CANCEL"
        }
        else{
            if (ret.CMD == "") {
                cmd = "CANCEL"
            } else {
                cmd = ret.CMD
            }
        }
        if (typeof(ret.dialogArguments) != 'undefined'){
            eval(ret.dialogArguments.OnCompleteFunctionName)(cmd, ret.dialogArguments.PostbackJS, ret.dialogArguments.PostbackArg, ret.dialogArguments.ExternalCallbackFunction);
        }
    }
}

function DefaultOnModalComplete(CMD, PostbackJS, PostbackArg, ExternalCallbackFunction) {

    //internal default implementation

    //alert('Cmd is ' + CMD)
    //PostbackJs will be a standard "__doPostback(target, arg)" 
    //PostbackArg is just the arg of the postback - not usefull here - but if
    //you provide your own OnCompleteFunctionName you can party on it client side if you want
    
    //default behavior - in 4.1 was to postback for no reason - no matter what happened in the modal
    
    //As of 5.0:
    //postbacks in the caller will only happen now if a MODAL SAVE verb fired in the modal 
    // - for CANCEL the modal will just close and go away - host page doesn't move 
    //Note that it is up to the modal control to provide the CMD via the AddDialogCloseScript - 4.1 and older
    //code did not do this and so all were being treated as CANCEL (which in the old days still round tripped you)
    
    // create your own OnComplete function if you don't want the default. You specify the name of 
    // that function when you create the ModalDialogRedirect verb. ExternalCallbackFunction is used by the api to 
    // provide api users a js callback mechanism that funnels safely through our internal ones - see api.js

    if (CMD == 'SAVE' || CMD == 'NEXT') {
        eval(PostbackJS)
    }
    
}

function ConvertModalFeatures(windowFeatures, height, width) {
    // takes windows features in ShowModalDialog() syntax and converts
    // them to window.open() syntax
    windowFeatures = windowFeatures.replace(";", ",");
    windowFeatures = windowFeatures.replace(/;/g,",");
    windowFeatures = windowFeatures.replace(/px/g,"");
    windowFeatures = windowFeatures.replace(/:/g,"=");
    windowFeatures = windowFeatures.replace(/dialogWidth/g,"width");
    windowFeatures = windowFeatures.replace(/dialogHeight/g,"height");
    windowFeatures = windowFeatures.replace(/scroll/g,"scrollbars");
    windowFeatures += ',left='+(screen.availWidth-width)/2+',top='+(screen.availHeight-height)/2;
    
    return windowFeatures;    
}

var lastmodalwindowtime = 0;


function _ModalDialogManager() {

    this.openModal = function (url, myDialogArguments, windowFeatures, onCloseCallback, height, width) {
        if (this.openingFakeModal) {
            return;
        }
        this.openingFakeModal = true;
        this.onCloseCallback = onCloseCallback;
        this.childsDialogArguments = myDialogArguments

        if (typeof (windowFeatures) == 'string') {
            windowFeatures = ConvertModalFeatures(windowFeatures, height, width)
        }

        this.result = null;
        this.closeHandled = false;

        this.attachParentWindowEvents();
        this.showModalMask();

        this.childWindow = window.open(url, '', windowFeatures);

        if (this.childWindow == null) {
            throw new Error(-1, "window has been blocked");
        }

        this.onCheckChildClosed();

        this.openingFakeModal = false;
    }

    this.showModalMask = function () {
        //disable scrolling of main window
        jQuery(window.document.body).css('overflow', 'hidden');

        this.modalMaskDiv = jQuery('<div/>');
        this.modalMaskDiv.css({
            'z-index': 400000,
            'position': 'absolute',
            'left': '0px',
            'top': '0px',
            'background-color': 'gray',
            'filter': 'alpha(opacity=60)',
            'opacity': 0.6,
            'MozOpacity': 0.6
        });
        this.modalMaskDiv.height(jQuery(document).height());
        this.modalMaskDiv.width(jQuery(document).width());

        //attach mask listener
        this.onParentFocusDelegate = jQuery.proxy(this, 'onParentFocus');
        this.modalMaskDiv.bind('click', this.onParentFocusDelegate);

        jQuery(document.body).append(this.modalMaskDiv);
    }

    this.hideModalMask = function () {
        if (this.modalMaskDiv) {
            this.modalMaskDiv.unbind('click', this.onParentFocusDelegate);
            this.modalMaskDiv.remove();
            this.modalMaskDiv = null;
        }

        //re-enable scrolling of parent window
        jQuery(document.body).css('overflow', 'auto');
    }

    this.attachParentWindowEvents = function () {
        this.onParentUnloadDelegate = jQuery.proxy(this, 'onParentUnload');
        jQuery(window).bind('unload', this.onParentUnloadDelegate);
    }

    this.detachParentWindowEvents = function () {
        jQuery(window).unbind('unload', this.onParentUnloadDelegate);
    }

    this.onParentFocus = function (e) {
        // bring modal into focus - front of screen 

        if (!this.childWindow) return;

        if (this.childWindow.closed) {
            this.onChildClosed();
            return;
        }

        this.childWindow.focus();

        return;
    }

    this.onParentUnload = function (e) {
        //hooked to modal caller to close modal if we leave this earth (back button, favorites, etc)

        if (!this.childWindow) return;

        try {
            this.childWindow.close();
        }
        catch (x) { }
    }

    this.onCheckChildClosed = function () {
        // This block suffers from a race condition.
        try {
            //timer for checking if the child window is closed because
            //not all browsers support the onunload event, like Opera...

            if (this.childWindow == null || this.childWindow.closed) {
                this.onChildClosed();
            }
            else {
                setTimeout(jQuery.proxy(this,'onCheckChildClosed'), 300);
            }
        }
        catch (e) {
            //eat this.
        }
    }

    this.onChildClosed = function (resultObj) {
        // modal was closed, clean up the UI

        if (this.closeHandled) return;
        this.closeHandled = true;

        this.result = resultObj
        try {

            if (!this.result) {
                //assume if nothing returned then modal window was killed
                this.result = {};
                this.result.CMD = "CANCEL";
            }

            //clear childsDialogArguments for a cancel so we don't postback on modals like modal redirect verbs
            if (this.result.CMD == "CANCEL") {
                this.childsDialogArguments = {}; 
            }

            // we need to keep dialogArguments passing along to ensure
            // the caller's callback function is called.
            this.result.dialogArguments = this.childsDialogArguments

            if (this.onCloseCallback) {
                this.onCloseCallback(this.result);
            }
        }
        catch (e) {
            //eat this.
        }
        finally {
            if (this.childWindow) {
                try {
                    this.childWindow.close();
                }
                //eat this for a permission issue when accessing childWindow.close() that only rarely happens in IE8.
                catch (e) { }
            }
            this.childWindow = null;
            this.result = null;

            this.hideModalMask();
            this.detachParentWindowEvents();
        }
    }

}
ModalDialogManager = new _ModalDialogManager();

//for backwards compat
var openFakeModal = ModalDialogManager.openModal;


var modallvl;


function Browser()
{
	var agent = new Object()
	try{agent.AgentName=navigator.userAgent.toLowerCase();}catch(e){agent.AgentName="";}
	agent.IsSafari=agent.AgentName.indexOf("safari")>=0;
	agent.IsOpera=agent.AgentName.indexOf("opera")>=0;
	agent.IsFireFox=agent.AgentName.indexOf("firefox")>=0;
	agent.IsIE=document.all!=null&&!agent.IsOpera&&!agent.IsSafari;
	
	return agent
}

//object used to call showModalDialog to show a usercontrol modally
function ModalDialogBB_crossbrowser(controlName, width, height, queryStringData, resizable, allowMaximize, useAdminPopup, dialogArguments) {

    try {
        this.AgentName = navigator.userAgent.toLowerCase();
    }
    catch (e) {
        this.AgentName = "";
    }

    //browser detection can not depend on presense of Atlas - cuteedit calls our modals from its own aspx pages...
    //detect the old fashioned way.
	this.IsSafari=this.AgentName.indexOf("safari")>=0;
	this.IsOpera=this.AgentName.indexOf("opera")>=0;
	this.IsFireFox=this.AgentName.indexOf("firefox")>=0;
	this.IsIE=document.all!=null&&!this.IsOpera&&!this.IsSafari;

	this.ctl = controlName;
	this.width = width;
	this.height = height;
	if (typeof (dialogArguments) == UNDEF)
	    this.dialogArguments = {};
	else
	    this.dialogArguments = dialogArguments;
	this.qsdata = queryStringData;
	this.features = "scroll:no;status:no;";
	this.Show = Show;
	this.GetURL = GetURL;
	this.getFeatureString = getFeatureString;
	if(typeof(modallvl)==UNDEF||modallvl<=0) {modallvl = 0;}
	if(typeof(resizable)==UNDEF||resizable) {this.resizable = 'yes'}else{this.resizable = 'no';}
	if(typeof(allowMaximize)==UNDEF||!allowMaximize) {this.maximize = 'no'}else{this.maximize = 'yes';}
	if (typeof (useAdminPopup) == UNDEF) {
	    useAdminPopup = true; 
    }

	function Show(onCloseCallback) {
	    var url = this.GetURL();

	    function openFakeModalCallback(retObj) {
	        modallvl--;
	        if (onCloseCallback) {
	            onCloseCallback(retObj);
	        }
	    }
	    ModalDialogManager.openModal(url, this.dialogArguments, this.getFeatureString(), openFakeModalCallback, height, width)

	    
	}

	function getFeatureString() {
        return "location:no;center:yes;"+this.features+"help:no;dialogWidth:"+this.width+"px;dialogHeight:"+this.height+"px;resizable:"+this.resizable+";maximize:"+this.maximize
	}

	function GetURL()
	{
	    if(typeof (this.ctl) == UNDEF) { alert("showModalDialogBB assert: ctl parameter not set in arg object") }
	    if(typeof (this.width) == UNDEF) { alert("showModalDialogBB assert: width parameter not set in arg object") }
	    if(typeof (this.height) == UNDEF) { alert("showModalDialogBB assert: height parameter not set in arg object") }
	    modallvl++;

	    var urlBase = (useAdminPopup ? "AdminPage.aspx" : "Popup.aspx");
	    
	    //if the modal request for the adminpage comes from an aspx page 
	    //not in the app root (e.g. cutesoft javascript) - the path to adminpage will be wrong 
	    //strip it down to the root location
	    var sLocURL = document.location.href
	    var iPos = sLocURL.indexOf('CuteSoft')
	    if(iPos != -1) {
	        urlBase = sLocURL.substring(0, iPos) + urlBase
	    }
	    else {
	        urlBase = ROOT_PATH + urlBase;
	    }

	    this.ctl = encodeURIComponent(this.ctl);

	    var bbec = "";
	    if (dialogArguments != null) {
	        if (typeof (dialogArguments) != UNDEF && (dialogArguments.hbc) != UNDEF && typeof (dialogArguments.SiteID) != UNDEF) {
	            bbec = "&SiteID=" + dialogArguments.SiteID + "&hbc=1";
	        }
	    }
       
	    if (bbec == "") {	   
	        var hbc = BLACKBAUD.netcommunity.GetQueryStringValue("hbc");
	        var siteId = BLACKBAUD.netcommunity.GetQueryStringValue("siteid");

	        if (hbc.length > 0 && siteId.length > 0) {
	            bbec = "&SiteID=" + encodeURIComponent(siteId) + "&hbc=" + encodeURIComponent(hbc);
	        }
	    }

	    var returnURL = urlBase + "?edit=3&md=" + modallvl + bbec + "&ctl=" + this.ctl + "&data=" + this.qsdata;
	    if (typeof (this.additionalQueryString) !== UNDEF) {
	        returnURL = returnURL + this.additionalQueryString;
	    }
	    
	    return returnURL;
	}
}


function GetPluginWrapperModalURL(ctl, data, plugin, dialogObject, postBackOnOk, useAdminPopup)
{
    var qsData = "ctl=" + ctl;
    qsData += "&data=" + data;
    qsData += "&pg=" + plugin;
    qsData += "&do=" + dialogObject;
    if(postBackOnOk)
    {
        qsData += "&pb=1";
    }

    var oModal = new ModalDialogBB_crossbrowser('~/Admin/TinyMCEPlugins/TinyMCEPluginWrapper.ascx', 0, 0, encodeURIComponent(qsData), true, true, useAdminPopup);
    
    return oModal.GetURL();
}
