/* ------------------------------------------------------------------------ *
 * SAS Institute, Inc.                                                      *
 *                                                                          *
 * Copyright (c) 2002-2007 SAS Institute, Inc.  All rights reserved.        *
 *                                                                          *
 * Contains utility classes and functions that provide additional           *
 * functionality needed by Citation dialogs. This functionality includes    *
 * support for mapping a dialog to a particular document in a parent window *
 * so that the dialog remains valid in the event the document is reloaded.  *
 * This functionality also includes support for displaying modal dialogs.   *
 *                                                                          *
 * Dependencies: citation_events.js                                         *
 * ------------------------------------------------------------------------ */
wrsProvide("citation_dialogUtils");
wrsRequire("citation",  SCRIPT_DIR, "citation_dialogUtils");

var g_modalDialogWarningMsg = "ERROR: could not configure modal dialog.  \nMake sure popup windows are not blocked in your browser.";

var cwDialogManager = { }; // No prototype used -- static object

// Is the current dialog (only one) that is open also modal?
cwDialogManager.modalDialog = null;

//Prefix appended to all dialogs opened by this dialog manager. The 
//default value is a string that allows easy identification of WRS 
//dialogs
cwDialogManager.dlgPrefix = 'SAS_WebReportStudio_Dialog';

//Suffix appended to all dialogs opened by this dialog manager. The 
//default value is a random integer between 0 and 100. Suggested usage 
//is to assign the sessionId or time at which the dialog is opened as 
//the value. Doing so will ensure that dialog names across user sessions are unique.
cwDialogManager.dlgSuffix = Math.floor(Math.random() * 100);

//Array manages refs to all modal (S0513257) dialogs opened or closed from the 
//current window. When the current window closes all open windows
//in this array should be closed as well:
cwDialogManager.dialogs = new Array();

// >>>>>>>>>>>>>>>>>>>>>>>>>>>>
// convenience keys used to retrieve a set of common windowFeatures
// >>>>>>>>>>>>>>>>>>>>>>>>>>
cwDialogManager["APPLIEDFILTERSTYLE"]           = "cwAppliedFiltersStyle";
cwDialogManager["ARCHIVED_REPORTS"]             = "cwArchivedReports";
cwDialogManager["BUILDER_AGGREGATION_DETAIL"]   = "WrsEdit_dialog_aggregationDetail";
cwDialogManager["BUILDER_BY_GROUP_LINK"]        = "WrsEdit_dialog_groupBreakLinking";
cwDialogManager["BUILDER_DEFINE_PROMPT"]        = "WrsEdit_dialog_definePrompt"; // Note (09/21/07) was undefined but referenced
cwDialogManager["BUILDER_DEFINE_GRAPH_PROMPT"]  = "WrsEdit_dialog_graphLinkPrompts";
cwDialogManager["BUILDER_DEFINE_GROUP_PROMPT"]  = "WrsEdit_dialog_groupLinkPrompts";
cwDialogManager["BUILDER_DEFINE_IMAGE_PROMPT"]  = "WrsEdit_dialog_imageLinkPrompts";
cwDialogManager["BUILDER_DEFINE_MAP_PROMPT"]    = "WrsEdit_dialog_mapLinkPrompts";
cwDialogManager["BUILDER_DEFINE_TABLE_PROMPT"]  = "WrsEdit_dialog_tableLinkPrompts";
cwDialogManager["BUILDER_DEFINE_TEXT_PROMPT"]   = "WrsEdit_dialog_textLinkPrompts";
cwDialogManager["BUILDER_EDIT_IMAGE"]       = "WrsEdit_dialog_editImage";
cwDialogManager["BUILDER_EDIT_IMAGE_NAV"]   = "cwBuilderEditImageNavigator";
cwDialogManager["BUILDER_EDIT_TEXT"]        = "WrsEdit_dialog_editText";
cwDialogManager["BUILDER_GALLERY_LAYOUT"]   = "WrsEdit_dialog_galleryLayout";
cwDialogManager["BUILDER_GEOMAP_DATA"]      = "WrsEdit_dialog_geomapData";
cwDialogManager["BUILDER_GRAPH_DATA"]       = "WrsEdit_dialog_graphData";
cwDialogManager["BUILDER_GRAPH_LINK"]       = "WrsEdit_dialog_graphLinking";
cwDialogManager["BUILDER_GRAPH_PROPERTIES"] = "WrsEdit_dialog_graphProperties";
cwDialogManager["BUILDER_GROUP_BREAKS"]     = "WrsEdit_dialog_groupBreaks";
cwDialogManager["BUILDER_HEADER_FOOTER"]    = "WrsEdit_dialog_headerFooter";
cwDialogManager["BUILDER_IMAGE_LINK"]            = "WrsEdit_dialog_imageLinking";
cwDialogManager["BUILDER_MAP_LINK"]              = "WrsEdit_dialog_mapLinking";
cwDialogManager["BUILDER_MAP_PROPERTIES"]   = "WrsEdit_dialog_mapProperties";
cwDialogManager["BUILDER_NEW_SECTION"]      = "WrsEdit_dialog_newSection";
cwDialogManager["BUILDER_PERCENT_DATA"]     = "WrsEdit_dialog_percentData";
cwDialogManager["BUILDER_RENAME_DATA"]      = "WrsEdit_dialog_renameData";
cwDialogManager["BUILDER_RENAME_SECTION"]   = "WrsEdit_dialog_renameSection";
cwDialogManager["BUILDER_REORDER_SECTIONS"] = "WrsEdit_dialog_reorderSections";
cwDialogManager["BUILDER_SELECT_DATA"]      = "WrsEdit_dialog_selectData";
cwDialogManager["BUILDER_TABLE_DATA"]       = "WrsEdit_dialog_tableData";
cwDialogManager["BUILDER_TABLE_LINK"]       = "WrsEdit_dialog_tableLinking";
cwDialogManager["BUILDER_TABLE_PROPERTIES"] = "WrsEdit_dialog_tableProperties";
cwDialogManager["BUILDER_TEXT_LINK"]        = "WrsEdit_dialog_textLinking";
cwDialogManager["BUILDER_TILE_PROPERTIES"]  = "WrsEdit_dialog_tileProperties";
cwDialogManager["CALCULATE_NEW_ITEM"]       = "cwCalculateItem";
cwDialogManager["CHOOSE_REPOSITORY"]        = "cwChooseRepository";
cwDialogManager["COMBINE_FILTERS"]          = "cwCombineFilters";
cwDialogManager["COPY_REPORT_LINK"]         = "cwCopyReportLink";
cwDialogManager["CREATE_FOLDER_DIALOG"]         = "cwCreateFolderDialog";
cwDialogManager["CUSTOM_FILTER"]                = "cwCustomFilter";
cwDialogManager["DATA_ITEM_PROPERTIES"]         = "cwDataItemProperties";
cwDialogManager["DATA_SOURCE_PROPERTIES"]       = "cwDataSourceProperties";
cwDialogManager["DEFINE_FORMAT"]                = "cwDefineFormat";
cwDialogManager["DRILL_TO_DETAIL"]              = "cwDrillToDetail";
cwDialogManager["EMAIL_REPORT"]                 = "cwEmailReport";
cwDialogManager["ESRI_IDENTIFY"]                = "cwESRIIdentify";
cwDialogManager["EXCEPTION_HIGHLIGHTING"]       = "cwExceptionHighlighting";
cwDialogManager["EXCEPTION_HIGHLIGHTING_CHART"] = "cwExceptionHighlightingChart";
cwDialogManager["EXPORT_TO_EXCEL_GRAPH"]        = "cwExportToExcelGraph";
cwDialogManager["EXPORT_TO_EXCEL_TABLE"]        = "cwExportToExcelTable";
cwDialogManager["EXPORT_TO_EXCEL_TABLE_OLAP"]   = "cwExportToExcelTableOlap";
cwDialogManager["FILTER_INFORMATION"]           = "cwFilterInfo";
cwDialogManager["GLOBAL_FILTERS"]               = "WrsEdit_globalFilters";
cwDialogManager["HELP_ABOUT"]                   ="cwHelpAbout";
cwDialogManager["HELP_DLG"]                     = "cwHelp";
cwDialogManager["INSERT_STORED_PROCESS"]    = "cwInsertStoredProcess";
cwDialogManager["ASSIGN_GROUP_BREAKS_TO_STORED_PROCESS"] = "cwAssignGroupBreaksToStoredProcess";
cwDialogManager["MANAGE_FILTER_PROMPTS"]    = "cwManagerFilterPrompts";
cwDialogManager["MANAGE_PASSWORDS"]         = "cwManagePasswords";
cwDialogManager["MEMBER_PROPERTIES"]        = "cwMemberProperties";
cwDialogManager["MOVE_COPY_FILE_DIALOG"]    = "cwMoveCopyFile";
cwDialogManager["OPEN_REPORT"]              = "cwOpenReport";
cwDialogManager["PAGE_SETUP"]               = "cwPageSetup";
cwDialogManager["PREFERENCES"]              = "cwPreferences";
cwDialogManager["PREVIEW_WIZARD_DATA"]      = "cwPreviewWizardData";
cwDialogManager["PRINT_OPTIONS"]            = "cwPrintOptions";
cwDialogManager["RANK_FILTER"]              = "cwRankFilter";
cwDialogManager["RECIPIENT_EDIT"]    = "cwRecipientEdit";
cwDialogManager["RECIPIENT_LIST_CREATE"]    = "cwRecipientListCreate";
cwDialogManager["RECIPIENT_RULES"]          = "cwRecipientRules";
cwDialogManager["RENAME_FILE_DIALOG"]       = "cwRenameFile";
cwDialogManager["REPAIR_REPORT"]            = "cwRepairReport";
cwDialogManager["REPORT_LINK_NEW_WINDOW"]   = "cwReportLinkNewWindow";
cwDialogManager["REPORT_PROPERTIES"]        = "cwReportProperties";
cwDialogManager["SAVE_OPTIONS"]             = "cwSaveOptions";
cwDialogManager["SCHEDULE_REPORT"]          = "cwScheduleReport";
cwDialogManager["SCHEDULE_TEST_SUMMARY"]    = 'cwScheduleTestSummary';
cwDialogManager["SCHEDULING_MANAGER"]       = "cwSchedulingManager";
cwDialogManager["SEARCH_DATA_ITEMS"]        = "cwSearchDataItems";
cwDialogManager["SELECT_INFORMATION_MAP"]   = "cwSelectInformationMap";
cwDialogManager["SORT"]                     = "cwSort";
cwDialogManager["STD_DLG_FEATURES"]         = "cwStandard"; //feature set for dialogs without explicitly defined keys
cwDialogManager["TOTALS"]                   = "cwTotals";
cwDialogManager["RELATIONAL_TOTALS"]        = "cwRelationalTotals";
cwDialogManager["ROLAP_TOTALS"]             = "cwROLAPTotals";
cwDialogManager["OLAP_FIND"]                = "cwOLAPFind";
cwDialogManager["COPY_SECTION"]             = "WrsEdit_dialog_copySection";
cwDialogManager["COMMENT_MANAGER"]          = "cwCommentManager";
cwDialogManager["EXPORT_TO_CI"]             = "cwExportToCI";

// Dialog features to be used only in an emergency when the AJAX call go get dimensions
// fails or times out:
cwDialogManager.defaultDialogFeatures = "width=640px,height=480px,resizable=yes,scrollbars=no";

// Note (09/21/07): cwDialogManager.featuresMap is no longer used.
// See CitationWebDimensions.properties instead, for initial dialog width,
// height, etc.  This change allows initial dialog sizes to be localized.

// Returns true if any dialog is open
cwDialogManager.isDialogOpen = function () {
    var isDlgOpen = false;
    for (var dlgName in cwDialogManager.dialogs) {
        var existDlg = cwDialogManager.dialogs[dlgName];
        isDlgOpen = (existDlg && existDlg.dlgWindow && !existDlg.dlgWindow.closed);
        if (isDlgOpen)
            break;
    }
    return isDlgOpen;
} 

cwDialogManager.getOpenDialog = function () {
   var isDlgOpen = false;  
   for (var dlgName in cwDialogManager.dialogs) {
     var existDlg = cwDialogManager.dialogs[dlgName];
     isDlgOpen = (existDlg && existDlg.dlgWindow && !existDlg.dlgWindow.closed);
     if (isDlgOpen){
         return existDlg;
     }  
   } 
   return null;
}   

  
// -----------------------------------------------------------------------------
// Opens and configures dialog with the specified features
//
// @param dlgUrl - url of the document to be displayed in the dialog.
// @param dlgName - name of the window containing the dlg (normally
// one of the constants in this file, e.g., cwDialogManager.BUILDER_TABLE_PROPERTIES).
// @param dlgFeaturesKey - A key (e.g. cwDialogManager.BUILDER_TABLE_PROPERTIES or
// the equivalent value, "WrsEdit_dialog_tableProperties"), used to look up the dialog features
// (width, height, etc.) in CitationWebDimensions.properties.  Or, for backward compatibility 
// only (deprecated because it does not support localization of initial dialog
// dimension), it may be the actual string of dialog features desired 
// (e.g., "width=640px,height=480px,resizable=yes").
// @param bReplaceUrl - boolean that specifies whether the entry in the window's
// history list should be replaced.
// @param bModal - boolean indicating whether the dialog should be modal
// @param bReplaceIfOpen - boolean that specifies whether the dialog should be
// opened with a new document if it is already open.
// @param onDlgClosingFunc - function to call immediately before dialog is closed
// as a result of a call to closeDialog, closeCwDialog and closeDialogWindow. NULL
// is allowed.
// @param onDlgClosedFunc - function to call immediately after dialog is closed
// as a result of a call to closeDialog, closeCwDialog and closeDialogWindow NULL
// is allowed.
// @param onDlgReadyFunc - optional function with signature (status, newDlg)
// where status will be 'ready' or 'exists' normally or 'error' or 'timeout'
// if there was a problem, and newDlg is the new dialog window or null if 
// it could not be successfully created.
// @return nothing meaningful
// -----------------------------------------------------------------------------
cwDialogManager.openDialog = function(
            dlgUrl,
            dlgNameParm,
            dlgFeaturesKey,
            bReplaceUrl,
            bModal,
            bReplaceIfOpen,
            onDlgClosingFunc,
            onDlgClosedFunc,
            onDlgReadyFunc
            )
{
    // Allow the name to be looked up. Or not.
    // e.g., either cwDialogManager.BUILDER_EDIT_TEXT or "WrsEdit_dialog_editText" 
    // can be passed to openDialog, which makes it easier
    // for Java code that ended up having hard-coded values
    // for whatever cwDialogManager.MY_DIALOG evaluated to in Javascript.
    var dlgName = cwDialogManager[dlgNameParm] ? cwDialogManager[dlgNameParm] : dlgNameParm;
   
    var existDlg = cwDialogManager.dialogs[dlgName];
    var isDlgOpen = (existDlg && existDlg.dlgWindow && !existDlg.dlgWindow.closed);
    if( !bReplaceIfOpen  && isDlgOpen )
    {
        existDlg.dlgWindow.focus();
        if (onDlgReadyFunc)
        {
            onDlgReadyFunc('exists', existDlg);
        }
        return null;
    }
    // Make sure another dialog is not open
    if (cwDialogManager.isDialogOpen()) 
    {
        if (onDlgReadyFunc)
        {
            onDlgReadyFunc('error', null);
        }
        return null;
    }

    // Collect needed parameters and info into a single payload object to simplify
    // the AJAX call and callback signatures:
    var payload = {dlgUrl:dlgUrl, dlgName:dlgName, features:dlgFeaturesKey, bReplaceUrl:bReplaceUrl, 
            bModal:bModal, bReplaceIfOpen:bReplaceIfOpen, onDlgClosingFunc:onDlgClosingFunc, 
            onDlgClosedFunc:onDlgClosedFunc, isDlgOpen:isDlgOpen, onDlgReadyFunc:onDlgReadyFunc};
            
    // Check for deprecated argument that is the literal dialog features string
    // instead of a key into CitationWebDimensions.properties:
    if (dlgFeaturesKey.match(/=/))  // Has "=", can't be a valid key?
    {
        // Assume correct dialog features string was passed in, do no further lookup
        return cwDialogManager.finishOpeningDialog(payload);
    } 
    else // normal
    { 
        // We are using key, not actual features string
        // Setup AJAX call to obtain (possibly locale-specific) dialog features
        // (in CitationWebDimensions.properties).
        var dlgFeaturesURL = "dialogFeatures.do?dialogName=" + dlgFeaturesKey + "&session=required";
        showDebugMsgs("cwDialogManager.openDialog()", "AJAX call dlgFeaturesURL="+dlgFeaturesURL);
        dojo.io.bind({
                url: dlgFeaturesURL,
                handle: function(type, evt, data)
                        { 
                            showDebugMsgs("cwDialogManager.openDialog", "Check for timeout.");
                            if (handleSessionTimeout(data, evt)) return;


                            if (type == "load") 
                            {
                                if (data.responseText.length > 0) // Normally true
                                {   
                                    payload.features = data.responseText; 
                                    showDebugMsgs("cwDialogManager.openDialog()", "AJAX call returned payload.features="+payload.features);                            
                                }
                                else // Should not happen
                                {
                                    showDebugMsgs("ERROR: cwDialogManager.openDialog()", "dialogFeatures AJAX call returned empty response.");                                    
                                    payload.features = cwDialogManager.defaultDialogFeatures;
                                }
                                return cwDialogManager.finishOpeningDialog(payload);
                            }
                        },
                error: function(type, error) 
                        {   // should not happen
                            showDebugMsgs("ERROR: cwDialogManager.openDialog()", "dialogFeatures AJAX call returned ERROR="+error);
                            showDebugMsgs("cwDialogManager.openDialog", "Check for timeout.");
                            if (handleSessionTimeout(data, evt)) return;

                            payload.features = cwDialogManager.defaultDialogFeatures;
                            return cwDialogManager.finishOpeningDialog(payload);
                        },
                mimetype: "text/plain"
                });
    }
    // This function no longer returns anything meaningful.
    // Deliberately trigger null pointer exception if misused:
    return null;    
}

// Callback function for AJAX call to finish opening the dialog using the actual 
// dialog features.
// The payload is an object that just contains all the needed parameters.
// Does not return anything meaningful
cwDialogManager.finishOpeningDialog = function(payload)
{
    // Extract passed arguments from payload
    var dlgUrl = payload.dlgUrl;
    var dlgName = payload.dlgName;
    var features = payload.features;
    var bReplaceUrl = payload.bReplaceUrl;
    var bModal = payload.bModal;
    var bReplaceIfOpen = payload.bReplaceIfOpen;
    var onDlgClosingFunc = payload.onDlgClosingFunc;
    var onDlgClosedFunc = payload.onDlgClosedFunc;
    var isDlgOpen = payload.isDlgOpen;
    var onDlgReadyFunc = payload.onDlgReadyFunc;

    try 
    {
        // get width and height from features for the window
        var widthRe = /width=\d+/g;
        var widthResult = features.match(widthRe);
        var width = 0;
        if (widthResult) 
        {
            width = parseInt(widthResult[0].substring(6));
        }      
        var heightRe = /height=\d+/g;
        var heightResult = features.match(heightRe);
        var height = 0;
        if (heightResult) 
        {
            height = parseInt(heightResult[0].substring(7));
        }      
        // calculate left and top so that the dialog is centered
        var left = parseInt((screen.availWidth/2) - (width/2));
        var top = parseInt((screen.availHeight/2) - (height/2));
        var extraFeatures = ",left=" + left + "px,top=" + top + "px";
      
        // append top and left to window features
        features = features + extraFeatures;
        var browserWindowName = null;
        if ( isDlgOpen ) 
        { //reuse existing dlg window name
            browserWindowName = existDlg.dlgWindow.name;
        } 
        else 
        {   
            //create unique window name so that window names across
            //user sessions don't collide. NOTE: The name supplied to the openDialog()
            //method is still the name that is used to obtain a reference to the dialog
            //window from cwDialogManager
            browserWindowName = cwDialogManager.dlgPrefix + dlgName + cwDialogManager.dlgSuffix;
        }
        showDebugMsgs("cwDialogManager.finishOpeningDialog", "open dialog URL="+dlgUrl
                    +", name="+browserWindowName
                    +", features="+features
                    +", replace="+bReplaceUrl);
                    
        
        var newDlgWin = window.open( dlgUrl, browserWindowName, features, bReplaceUrl );
        //tag window so that we can easily detect that we opened it
        try 
        {
             newDlgWin._cwManagerOpenedBy = cwDialogManager;    
             showDebugMsgs("cwDialogManager.finishOpeningDialog", "tagged " + newDlgWin.name + " opened by " + newDlgWin._cwManagerOpenedBy + " opener: " + newDlgWin.opener);
        } 
        catch (e) 
        {
            showDebugMsgs("ERROR: cwDialogManager.finishOpeningDialog", "exception caught tagging dlg window in openDialog.")
        }      
        try 
        {
            // commented out next line - if window is not modal, then can't set the property (throws exception) - S0467113
            // newDlgWin.cwIsModal = ( bModal != null ? bModal : false );
            if( bModal != null && bModal ) 
            {
                cwDialogManager.configureModalDialog( newDlgWin, bModal );
            }
        } 
        catch (e) 
        {
            if (isBrowserFirefox())
            {
               alert(g_modalDialogWarningMsg);
            }   
            showDebugMsgs("cwDialogManager.finishOpeningDialog", "ERROR: could not configure modal dialog. Make sure popup windows are not blocked in your browser.");
        }
        var newDlg = new cwDialog(newDlgWin);
        if (bModal) // S0513257 - only manange modal dialogs:
        {
            cwDialogManager.dialogs[browserWindowName] = newDlg;
        }
      
        if( onDlgClosingFunc != null ) 
        {
            registerEventHandler ( newDlg, "WINDOW_CLOSING", onDlgClosingFunc, false );
        }      
        if( onDlgClosedFunc != null ) 
        {
            registerEventHandler ( newDlg, "WINDOW_CLOSED", onDlgClosedFunc, false );
        }      
        try 
        {
            newDlgWin.focus();
        } 
        catch (e) 
        {
            showDebugMsgs("ERROR: cwDialogManager.finishOpeningDialog", "Exception caught in setting focus on new dialog window.");
        }
        if (onDlgReadyFunc)
        {
            try {
                onDlgReadyFunc('ready', newDlg);               
            }
            catch (e)
            {
                showDebugMsgs("ERROR: cwDialogManager.finishOpeningDialog", "Exception caught calling onDlgReadyFunc.");                
            }
        }
    } 
    catch (bigEx) 
    {
        alert("General problem with opening the dialog window: \n" + bigEx.message);
    }
    return null;
}

cwDialogManager.closeSelf = function()
{
    var winOpener = self.opener; 
    if( winOpener != null && winOpener.cwDialogManager != null) {
        winOpener.cwDialogManager.closeDialogWindow( self ); // op succeeded so close the dialog and dispatch WINDOW_CLOSING & WINDOW_CLOSED events
    } else {
        cwDialogManager.closeDialogWindow( self );
    }
}

cwDialogManager.cancelSelf = function()
{
	try {	// (S0541117) Needed for session timeout, when cwDialogManager is gone on root window
        var winOpener = self.opener; 
        if( winOpener != null && winOpener.cwDialogManager != null) {
            winOpener.cwDialogManager.cancelDialogWindow( self ); // op succeeded so close the dialog and dispatch WINDOW_CLOSING & WINDOW_CLOSED events
        } else {
            cwDialogManager.cancelDialogWindow( self );
        }
    }
    catch(ex) {
        cwDialogManager.cancelDialogWindow( self );    
    }
}
    
// -----------------------------------------------------------------------------
// Closes a dialog of the particular name. The dialog must have been opened
// using cwDialogManager.openDialog().
//
// @param dlgName - the name of dialog to close
// -----------------------------------------------------------------------------
cwDialogManager.closeDialog = function( dlgName )
{
    var dlgToClose = cwDialogManager.dialogs[dlgName];
    return cwDialogManager.closeDialogWindow(dlgToClose.dlgWindow);
}

// -----------------------------------------------------------------------------
// Closes a dialog of the particular name. The dialog must have been opened
// using cwDialogManager.openDialog().
//
// @param dlgName - the name of dialog to close
// -----------------------------------------------------------------------------
cwDialogManager.closeCwDialog = function( cwDialog )
{
    return cwDialogManager.closeDialogWindow(cwDialog.dlgWindow);
}

// -----------------------------------------------------------------------------
// Closes a dialog window. The method can be used to close windows that were not
// opened using cwDialogManager.openDialog(), but it's primary intent is for
// closing dialogs that were. For example, it performs all needed cleanup for
// modal dialogs opened using cwDialogManager.openDialog(). The method also
// is useful because it dispatches "WINDOW_CLOSING" and "WINDOW_CLOSED" events
// to listeners registered on the dlg using the registerEventHandler() method
// in citation_events.js.
//
// @param dlgToClose - the dialog window object
// -----------------------------------------------------------------------------
cwDialogManager.closeDialogWindow = function( winToClose )
{
    // as of 12-02-02 store using actual window name as key
    var dlgToClose = cwDialogManager.dialogs[winToClose.name]; //may be null
    if( winToClose != null && !winToClose.closed )
    {
        // Closed implies not modal otherwise we experience double href submits. [S0498391]
        // The event does not get unregistered when it should.
        //if( winToClose.cwIsModal != null && winToClose.cwIsModal )
        //{
            /* unreg all modality settings */
            cwDialogManager.configureModalDialog( winToClose, false );
        //}

        if( dlgToClose != null )
        {
            //dispatch WINDOW_CLOSING event
            var closingEvent = eventNotify.eventFactory.createEvent(dlgToClose, "WINDOW_CLOSING", false /*no bubbling*/);
            eventNotify_lw( dlgToClose, closingEvent, true /*a custom event*/ );
        }
        winToClose.close();

        if( dlgToClose != null )
        {
            //dispatch WINDOW_CLOSED event
            var closedEvent = eventNotify.eventFactory.createEvent(dlgToClose, "WINDOW_CLOSED", false /*no bubbling*/ );
            eventNotify_lw( dlgToClose, closedEvent, true /*a custom event*/ );
            //cwDialogManager.dialogs[dlgName] = null;
        }
    }

    return dlgToClose;
}

// -----------------------------------------------------------------------------
// This method can be called from a dialog windows close button's onclick 
// parameter. This will close the dialog and fire off a window canceled event
// to any listeners that have registered for it. This allows a calling page
// to know if the dialog was exited using the cancel button (versus the OK).
// This will not be sufficient if the user X'ed out of the dialog.
//
// @param dlgToClose - the dialog window object
// -----------------------------------------------------------------------------
cwDialogManager.cancelDialogWindow = function(winToClose)
{
    // Close the dialog but do not fire the closing and the closed events
    // for the cancel dialog.
    var dlgToClose = cwDialogManager.dialogs[winToClose.name]; //may be null
    if( winToClose != null && !winToClose.closed )
    {
        if( winToClose.cwIsModal != null && winToClose.cwIsModal )
        {
            /* unreg all modality settings */
            cwDialogManager.configureModalDialog( winToClose, false );
        }

        winToClose.close();
    }    
    
    if(dlgToClose != null)
    {
        //dispatch WINDOW_CANCELED event
        var cancelEvent = eventNotify.eventFactory.createEvent(dlgToClose, "WINDOW_CANCELED", false /*no bubbling*/ );
        showDebugMsgs("cancelDialogWindow", "Dialog manager firing off window canceled event");
        eventNotify_lw(dlgToClose, cancelEvent, true /*a custom event*/ );
    }
}

// -----------------------------------------------------------------------------
// unload handler function responsible for closing all child dialogs of the
// current window
// -----------------------------------------------------------------------------
cwDialogManager.dependencyMgr = function( event )
{
    var evt = (event != null ? event : window.event);
    // var evtTarget = (evt.target != null ? evt.target : evt.srcElement);
    
    if( evt.type == "unload" ) 
    {
        for( var dlgName in cwDialogManager.dialogs)
        {
            var currDlg = cwDialogManager.dialogs[dlgName];
            cwDialogManager.closeDialog( currDlg.name );
        }
    }
}

/**
 * Enforce that all page access occurs from a logged on session.
 * To be called at the top of pages when main application window pages are
 * attempted access from outside the main application window.
 */
cwDialogManager.enforceWindowHosting = function (rootAppWindowLocation)
{
    //var rootAppWindow = cwDialogManager._getRootApplicationWindow(window);
    
    var rootAppWindow = null;
    try
    {
	    rootAppWindow = window.top;	// S0541117
    }
    catch (ex)
    {
    	return;
    }
    
    if (rootAppWindow == window)
    {
        return;
    }
    
    // -- rootAppWindow is not the current window --
    var rootDescendants = cwDialogManager.getDescendantWindows(rootAppWindow);
    //close descendants
    for (var i=0; i<rootDescendants.length; i++)
    {
        var descendant = rootDescendants[i];
        descendant.close();
    }
    rootAppWindow.location = rootAppWindowLocation;   
    //close this window in case it was not recognized as a descendant.
    if (!window.closed)
    {
        window.close();
    }
}

//  FUNCTION NO LONGER USED (brcarb - 10/16/08 S0541117):
cwDialogManager._getRootApplicationWindow = function (windowRef)
{
    if (windowRef.parent != null && windowRef.parent != windowRef)
    {
        // WindowRef is most likely a remote scripting iframe (but perhaps another type of
        // frame which we claim no support for). This can happen quite frequently
        // in the builder where the iframe processes an intermediary request before
        // the final request to open a dialog is submitted. In such case, the intermediary
        // request needs to be equipped to locate the root app window.
        
        //CAUTION: Access to window names is not always reliable for frames 
        //and iframes. Hence call to showDebugMsgs should never be live in production.  
        //showDebugMsgs("cwDialogManager._getRootApplicationWindow", " window name: " + windowRef.name +  " parent: " + parent.name);
        
        var rootCandidate = windowRef;
        while (rootCandidate.parent != rootCandidate
                && rootCandidate.parent != null
                && rootCandidate.parent.cwDialogManager != null)
        {
            rootCandidate = rootCandidate.parent;
        }
        //showDebugMsgs("getRootApplicationWindow", " returning parent: " + rootCandidate.name);
        return rootCandidate;
    }

    var root = windowRef;
    if (root.opener != null)
    {
        // showDebugMsgs("_getRootApplicationWindow", "opener: " + root.opener.name);
        while ( root.opener != null
                && root.opener.cwDialogManager != null
                && root.opener.cwDialogManager.isManaged(root))
        {
            // showDebugMsgs("_getRootApplicationWindow", " follow opener link of: " + root.name + " root opener name: " + root.opener.name);
            root = root.opener;
        }
    }
    // showDebugMsgs("_getRootApplicationWindow", " returning : " + root.name);
    return root;
}

 
cwDialogManager.getDescendantWindows = function (windowRef)
{
    var descendants = new Array();
    cwDialogManager._getDescendantWindows(windowRef, descendants);
    return descendants;
}

cwDialogManager._getDescendantWindows = function (windowRef, descendants)
{
    var dlgManager = windowRef.cwDialogManager;
    if (dlgManager == null) 
    {
        return;
    }
    
    for( var i = 0; i<dlgManager.dialogs.length; i++ )
    {
        var currDlg = dlgManager.dialogs[i];
        descendants[descendants.length] = currDlg.dlgWindow;
        cwDialogManager._getDescendantWindows(currDlg.dlgWindow, descendants);
    }
}

//Returns true if the specified dialog is managed by
//the dialog manager. Returns false otherwise. A dialog
//is considered managed by the manager if it was opened
//by the manager. 
cwDialogManager.isManaged = function(windowRef)
{
    if (windowRef._cwManagerOpenedBy == cwDialogManager)
    {
        return true;
    }
    
    for( var dlgName in cwDialogManager.dialogs)
    {
        var dlg = cwDialogManager.dialogs[dlgName];
        if (dlg.dlgWindow == windowRef) 
        {
            //showDebugMsgs("isManaged", windowRef.name + " IS in list of managed dialogs under " + window.name );
            return true;
        }
    }
    //showDebugMsgs("isManaged", windowRef.name + " is not a managed dialog.");
    return false;    
}
// ----------------------------------------------------------
// Configure is used both to set up and to take down a dialog
// ----------------------------------------------------------
cwDialogManager.configureModalDialog = function( dlg, setModal )
{
    dlg.cwIsModal = ( setModal != null ? setModal : true );
    
    if( dlg.cwIsModal ) 
    {
        var bRegisterListener = (cwDialogManager.modalDialog == null);
        cwDialogManager.modalDialog = dlg;
        if( bRegisterListener ) 
        {
            // previous modal dialog has not been opened from the current window 
            // so focus listener needs be registered
            // handler should capture the events so not seen by individual
            // areas of the window.
            registerEventHandler( window, "focus", cwDialogManager.modalityMgr, true );
            registerEventHandler( window, "resize", cwDialogManager.modalityMgr, true);
            registerEventHandler( window.document, "click", cwDialogManager.modalityMgr, true);
            registerEventHandler( window.document, "oncontextmenu", cwDialogManager.modalityMgr, true);  // (brcarb 02/04/08) Is this really needed?
            registerEventHandler( window.document, "keydown", cwDialogManager.modalityMgr, true);
            registerEventHandler( window.document, "mousedown", cwDialogManager.modalityMgr, true);
            registerEventHandler( window.document, "mouseup", cwDialogManager.modalityMgr, true);
            registerEventHandler( window.document, "dragstart", cwDialogManager.modalityMgr, true); // (S0643055)
        }
    } 
    else 
    {
        unRegisterEventHandler( window, "focus", cwDialogManager.modalityMgr, true );
        unRegisterEventHandler( window, "resize", cwDialogManager.modalityMgr, true );
        unRegisterEventHandler( window.document, "click", cwDialogManager.modalityMgr, true );
        unRegisterEventHandler( window.document, "oncontextmenu", cwDialogManager.modalityMgr, true );   // (brcarb 02/04/08)     
        unRegisterEventHandler( window.document, "keydown", cwDialogManager.modalityMgr, true );
        unRegisterEventHandler( window.document, "mousedown", cwDialogManager.modalityMgr, true );
        unRegisterEventHandler( window.document, "mouseup", cwDialogManager.modalityMgr, true );
        unRegisterEventHandler( window.document, "dragstart", cwDialogManager.modalityMgr, true );	// (S0643055)
      
        cwDialogManager.modalDialog = null;
    }
}

// onfocus handler to reassign focus to the modal dialog
// when the user attempts to move focus to main parent window
cwDialogManager.modalityMgr = function( e )
{
    var evt = (e != null ? e : window.event);
    var evtTarget = (evt.target != null ? evt.target : evt.srcElement);

    // veto events on the current window if there is a modal 
    // dialog open when the event is triggered.
    
    // (S0374890) Try/catch to workaround issue with 08/14/06 IE patch:
    try 
    {
        if( cwDialogManager.modalDialog != null)
        {
             
            if (cwDialogManager.modalDialog.closed)
            {
                showDebugMsgs("cwDialogManager.modalityMgr", 
                    "Modal dialog manager did not trap event.  Modal window already closed.  ");
                //Modal window was closed w/out going through app (e.g. 'x' button was pressed)
                //In such cases detaching modal listener within an event handler can be problematic.
                //So simply cease trapping events in such cases. If events continue to be 
                //trapped, it can prevent further interaction with the parent of the closed
                //modal window.
                return; //no return value (not even TRUE) see S0495323
                
                /* unregister all event modality settings */ 
                //cwDialogManager.configureModalDialog( cwDialogManager.modalDialog, false);
            }
            else
            {       
                cwAbsorbEvent(evt);
                evt.returnValue = false;  
                showDebugMsgs("cwDialogManager.modalityMgr", "focus returned to dialog " + cwDialogManager.modalDialog.name);
                // Make sure any open popups get closed
                dojo.event.topic.publish("Components.ClosePopups");
                cwDialogManager.modalDialog.focus();
                return false;
            }
        }        
    } 
    catch (e) 
    {
        showDebugMsgs("cwDialogManager.modalityMgr", "caught focus error in cwDialogManager.modalityMgr");
    }   
    return;
}

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// functions needed to map a dialog to a parent window
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

// variables used by the dialog manager. These variables should be set based
// on the needs of the dialog
cwDialogManager.appContext = null; // required -- used to detect when location of parent window moves outside our web context
cwDialogManager.conditionVariableName = "g_wizardStep"; //default
cwDialogManager.conditionValue = 1; //default
//Flag that indicates if parent window's document is valid for this document.
//Used by removeParentDependencies to determine if it should actually remove
//parent dependencies upon closing of the dialog.
cwDialogManager.isParentDocumentValid = true;

// -----------------------------------------------------------------------------
// This function is assigned in a dialog and entirely optional. Its job is to
// attach any custom dependencies to the parent. If set, this function will be
// called as part of the initializeParentDependencies() method.
// -----------------------------------------------------------------------------
cwDialogManager.attachCustomParentDependenciesFunction = null;

// -----------------------------------------------------------------------------
// To map the dialog to its parent initially this function should be called by
// the dialog when it is first opened.  Whenever it is necessary to remap the
// dialog to the parent window (e.g. in cases when the parent reloads its
// document but the dialog should remain open) cwDialogManager will make
// subsequent calls to this function to remap the dialog.
// -----------------------------------------------------------------------------
cwDialogManager.initializeParentDependencies = function()
{
    registerEventHandler ( self.opener, "unload", cwDialogManager.onParentUnload, false );
    //registerEventHandler( self, "unload", cwDialogManager.removeParentDependencies, false );

    if( cwDialogManager.attachCustomParentDependenciesFunction != null )
    {
        cwDialogManager.attachCustomParentDependenciesFunction();
    }

    //alert("initializing Dependencies complete");
}

cwDialogManager.onParentUnload = function()
{
    // a 2 second delay, give parent window time to change its href
    setTimeout("cwDialogManager.validateParentDialogDependency()", 2000)
}

// -----------------------------------------------------------------------------
// In the event the parent window unloads its document, this function determines
// if the dialog should remain open. If so, it remaps the dialog to the parent
// window.  Otherwise, it closes the dialog.
// -----------------------------------------------------------------------------
cwDialogManager.validateParentDialogDependency = function()
{
    try {
        if( !cwDialogManager.leaveDialogOpenOk() )
        {
            //set flag indicating parent dependencies should be removed upon unloading of dialog's document
            cwDialogManager.isParentDocumentValid = false;
            self.close();
        }
        else 
        {
            cwDialogManager.remapDialog();
        }
    }
    catch(e) 
    {
        //set flag indicating parent dependencies should be removed upon unloading of dialog's document
        cwDialogManager.isParentDocumentValid = false;

        //Catch the error that might be thrown. (e.g. when an attempt is made to read location from different
        //web server.   Leaving the server serving this app => close the dialog
        self.close();
    }

}

// -----------------------------------------------------------------------------
// Remaps the dialog to the parent window once the parent window's document
// has been fully loaded.
// -----------------------------------------------------------------------------
cwDialogManager.remapDialog = function()
{
    if( self.opener.g_pageLoaded != null && !self.opener.g_pageLoaded ) 
    {
        //alert("parent still not loaded");
        setTimeout( "cwDialogManager.remapDialog()", 1000);
    }
    else 
    { //remap the dialog
        //alert("remapping dialog");
        cwDialogManager.initializeParentDependencies();
        return;
    }

}

// -----------------------------------------------------------------------------
// If the parent window reloads its document and the conditionVariable
// and its value remain the same for the parent, then this function returns
// true indicating that the dialog should remain open if already so. Otherwise,
// this function returns false;
// -----------------------------------------------------------------------------
cwDialogManager.leaveDialogOpenOk = function()
{
    //alert("testing if ok to leave up dialog");
    try {
        var parentSite = self.opener.location.href;

        var strToEval = "self.opener." + cwDialogManager.conditionVariableName + ";"
        var conditionVariable = eval(strToEval);
        //alert("conditionVariable Value = " + conditionVariable + "\ndialogMgr value = " + cwDialogManager.conditionValue );
        if( conditionVariable  == null
                || conditionVariable != cwDialogManager.conditionValue
                || parentSite.indexOf(cwDialogManager.appContext) == -1 )
        {
            //same server different webapp => close dialog
            return false;
        }
    }
    catch(e) 
    {
        //leaving the server serving this app
        return false;
    }
    return true;
}

//Responsible for unmapping the dialog in the event it is closed while parent
//window still open
cwDialogManager.removeParentDependencies = function()
{
    if( !cwDialogManager.isParentDocumentValid )
    {
        unRegisterEventHandler( self.opener, "unload", cwDialogManager.removeParentDependencies, false );
        showDebugMsgs("cwDialogManager.removeParentDependencies", "...parent dependencies removed.");
    }
}

// -----------------------------------------------------------------------------
// cwDialog class - a dialog has an associated window and a set of event
// listeners. The purpose of associating event listeners with a cwDialog object
// is so that listeners can remain associated with the dialog even after the
// the dialog has been closed or the window's document has been unloaded or reloaded.
//
// NOTE: Listeners registered on the dialog object are mainly for use by objects
// outside the dialog's window.
// -----------------------------------------------------------------------------
cwDialog.prototype.addEventListener = cwAddEventListener;
cwDialog.prototype.removeEventListener = cwRemoveEventListener;
cwDialog.prototype.dispatchEvent = cwDispatchEvent;

function cwDialog(dlgWin)
{
    this.dlgWindow = dlgWin;
}

